Merge "Support multiple locales in distractor filter."
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
index 95df202..9cfcc3d 100644
--- a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
@@ -16,22 +16,12 @@
 
 package com.android.inputmethod.latin.utils;
 
-import android.content.Context;
-
 import com.android.inputmethod.latin.RichInputMethodManager;
 import com.android.inputmethod.latin.settings.SettingsValues;
 
 public final class StatsUtils {
-    public static void init(final Context context) {
-    }
 
     public static void onCreate(final SettingsValues settingsValues,
             RichInputMethodManager richImm) {
     }
-
-    public static void onLoadSettings(final SettingsValues settingsValues) {
-    }
-
-    public static void onDestroy() {
-    }
 }
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java
new file mode 100644
index 0000000..120b105
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+
+package com.android.inputmethod.latin.utils;
+
+import android.content.Context;
+
+import com.android.inputmethod.latin.settings.SettingsValues;
+
+public class StatsUtilsManager {
+
+    private static final StatsUtilsManager sInstance = new StatsUtilsManager();
+
+    /**
+     * @return the singleton instance of {@link StatsUtilsManager}.
+     */
+    public static StatsUtilsManager getInstance() {
+        return sInstance;
+    }
+
+    public void onCreate(final Context context) {
+    }
+
+    public void onLoadSettings(final SettingsValues settingsValues) {
+    }
+
+    public void onDestroy() {
+    }
+}
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index f37f6cc..a1ffe5a 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -82,6 +82,7 @@
                 <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
                 <action android:name="android.intent.action.USER_INITIALIZE" />
+                <action android:name="android.intent.action.LOCALE_CHANGED" />
             </intent-filter>
         </receiver>
 
diff --git a/java/res/layout/additional_subtype_dialog.xml b/java/res/layout/additional_subtype_dialog.xml
index f97c006..b7804f5 100644
--- a/java/res/layout/additional_subtype_dialog.xml
+++ b/java/res/layout/additional_subtype_dialog.xml
@@ -18,39 +18,60 @@
 */
 -->
 
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:columnCount="2"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:layout_marginLeft="8dip"
-    android:layout_marginRight="8dip"
-    android:padding="8dip">
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="left|center_vertical"
-        style="?android:attr/textAppearanceSmall"
-        android:text="@string/subtype_locale" />
-    <Spinner
-        android:id="@+id/subtype_locale_spinner"
-        android:layout_width="wrap_content"
-        android:layout_marginLeft="8dip"
-        android:layout_marginBottom="8dip"
-        android:layout_marginTop="8dip"
-        android:layout_gravity="fill_horizontal|center_vertical"
-        android:prompt="@string/subtype_locale" />
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="left|center_vertical"
-        style="?android:attr/textAppearanceSmall"
-        android:text="@string/keyboard_layout_set" />
-    <Spinner
-        android:id="@+id/keyboard_layout_set_spinner"
-        android:layout_width="wrap_content"
-        android:layout_marginLeft="8dip"
-        android:layout_marginBottom="8dip"
-        android:layout_marginTop="8dip"
-        android:layout_gravity="fill_horizontal|center_vertical"
-        android:prompt="@string/keyboard_layout_set" />
-</GridLayout>
+    android:padding="16dip">
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <TextView
+            android:layout_width="0dp"
+            android:layout_weight="30"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start|center_vertical"
+            android:gravity="start|left"
+            android:textAlignment="viewStart"
+            style="?android:attr/textAppearanceSmall"
+            android:text="@string/subtype_locale" />
+        <Spinner
+            android:id="@+id/subtype_locale_spinner"
+            android:spinnerMode="dialog"
+            android:layout_width="0dp"
+            android:layout_weight="70"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="8dip"
+            android:layout_marginBottom="8dip"
+            android:layout_marginTop="8dip"
+            android:layout_gravity="fill_horizontal|center_vertical"
+            android:gravity="start|left"
+            android:prompt="@string/subtype_locale" />
+        </LinearLayout>
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <TextView
+            android:layout_width="0dp"
+            android:layout_weight="30"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start|center_vertical"
+            android:textAlignment="viewStart"
+            style="?android:attr/textAppearanceSmall"
+            android:text="@string/keyboard_layout_set" />
+        <Spinner
+            android:id="@+id/keyboard_layout_set_spinner"
+            android:spinnerMode="dialog"
+            android:layout_width="0dp"
+            android:layout_weight="70"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="8dip"
+            android:layout_marginBottom="8dip"
+            android:layout_marginTop="8dip"
+            android:layout_gravity="fill_horizontal|center_vertical"
+            android:gravity="start|left"
+            android:prompt="@string/keyboard_layout_set" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml
index d42b4e9..5453d51 100644
--- a/java/res/values/colors.xml
+++ b/java/res/values/colors.xml
@@ -82,4 +82,6 @@
     <color name="setup_text_action">@android:color/holo_blue_light</color>
     <color name="setup_step_background">@android:color/background_light</color>
     <color name="setup_welcome_video_margin_color">#FFCCCCCC</color>
+    <!-- Accent color for the notification. We need to match this to the OS build -->
+    <color name="notification_accent_color">#FF607D8B</color>
 </resources>
diff --git a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
new file mode 100644
index 0000000..eb18007
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package com.android.inputmethod.compat;
+
+import android.app.Notification;
+import android.os.Build;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class NotificationCompatUtils {
+    // Note that TextInfo.getCharSequence() is supposed to be available in API level 21 and later.
+    private static final Method METHOD_setColor =
+            CompatUtils.getMethod(Notification.Builder.class, "setColor", int.class);
+    private static final Method METHOD_setVisibility =
+            CompatUtils.getMethod(Notification.Builder.class, "setVisibility", int.class);
+    private static final Method METHOD_setCategory =
+            CompatUtils.getMethod(Notification.Builder.class, "setCategory", String.class);
+    private static final Method METHOD_setPriority =
+            CompatUtils.getMethod(Notification.Builder.class, "setPriority", int.class);
+    private static final Method METHOD_build =
+            CompatUtils.getMethod(Notification.Builder.class, "build");
+    private static final Field FIELD_VISIBILITY_SECRET =
+            CompatUtils.getField(Notification.class, "VISIBILITY_SECRET");
+    private static final int VISIBILITY_SECRET = null == FIELD_VISIBILITY_SECRET ? 0
+            : (Integer) CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */,
+                    FIELD_VISIBILITY_SECRET);
+    private static final Field FIELD_CATEGORY_RECOMMENDATION =
+            CompatUtils.getField(Notification.class, "CATEGORY_RECOMMENDATION");
+    private static final String CATEGORY_RECOMMENDATION = null == FIELD_CATEGORY_RECOMMENDATION ? ""
+            : (String) CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */,
+                    FIELD_CATEGORY_RECOMMENDATION);
+    private static final Field FIELD_PRIORITY_LOW =
+            CompatUtils.getField(Notification.class, "PRIORITY_LOW");
+    private static final int PRIORITY_LOW = null == FIELD_PRIORITY_LOW ? 0
+            : (Integer) CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */,
+                    FIELD_PRIORITY_LOW);
+
+    private NotificationCompatUtils() {
+        // This class is non-instantiable.
+    }
+
+    // Sets the accent color
+    public static void setColor(final Notification.Builder builder, final int color) {
+        CompatUtils.invoke(builder, null, METHOD_setColor, color);
+    }
+
+    public static void setVisibilityToSecret(final Notification.Builder builder) {
+        CompatUtils.invoke(builder, null, METHOD_setVisibility, VISIBILITY_SECRET);
+    }
+
+    public static void setCategoryToRecommendation(final Notification.Builder builder) {
+        CompatUtils.invoke(builder, null, METHOD_setCategory, CATEGORY_RECOMMENDATION);
+    }
+
+    public static void setPriorityToLow(final Notification.Builder builder) {
+        CompatUtils.invoke(builder, null, METHOD_setPriority, PRIORITY_LOW);
+    }
+
+    public static Notification build(final Notification.Builder builder) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            // #build was added in API level 16, JELLY_BEAN
+            return (Notification) CompatUtils.invoke(builder, null, METHOD_build);
+        } else {
+            // #getNotification was deprecated in API level 16, JELLY_BEAN
+            return builder.getNotification();
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
index afbe8c8..0f00be1 100644
--- a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
@@ -34,6 +34,9 @@
     // Note that View.setElevation(float) has been introduced in API level 21.
     private static final Method METHOD_setElevation = CompatUtils.getMethod(
             View.class, "setElevation", float.class);
+    // Note that View.setTextAlignment(int) has been introduced in API level 17.
+    private static final Method METHOD_setTextAlignment = CompatUtils.getMethod(
+            View.class, "setTextAlignment", int.class);
 
     private ViewCompatUtils() {
         // This utility class is not publicly instantiable.
@@ -56,9 +59,19 @@
     }
 
     public static void setElevation(final View view, final float elevation) {
-        if (METHOD_setElevation == null) {
-            return;
-        }
         CompatUtils.invoke(view, null, METHOD_setElevation, elevation);
     }
+
+    // These TEXT_ALIGNMENT_* constants have been introduced in API 17.
+    public static final int TEXT_ALIGNMENT_INHERIT = 0;
+    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
+    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
+    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
+    public static final int TEXT_ALIGNMENT_CENTER = 4;
+    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
+    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
+
+    public static void setTextAlignment(final View view, final int textAlignment) {
+        CompatUtils.invoke(view, null, METHOD_setTextAlignment, textAlignment);
+    }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
index 95a0942..6fbca44 100644
--- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
@@ -31,12 +31,14 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.net.ConnectivityManager;
 import android.net.Uri;
+import android.os.Build;
 import android.os.ParcelFileDescriptor;
 import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.inputmethod.compat.ConnectivityManagerCompatUtils;
 import com.android.inputmethod.compat.DownloadManagerCompatUtils;
+import com.android.inputmethod.compat.NotificationCompatUtils;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.utils.ApplicationUtils;
 import com.android.inputmethod.latin.utils.DebugLogUtils;
@@ -858,7 +860,7 @@
         final String language = (null == locale ? "" : locale.getDisplayLanguage());
         final String titleFormat = context.getString(R.string.dict_available_notification_title);
         final String notificationTitle = String.format(titleFormat, language);
-        final Notification notification = new Notification.Builder(context)
+        final Notification.Builder builder = new Notification.Builder(context)
                 .setAutoCancel(true)
                 .setContentIntent(notificationIntent)
                 .setContentTitle(notificationTitle)
@@ -866,8 +868,13 @@
                 .setTicker(notificationTitle)
                 .setOngoing(false)
                 .setOnlyAlertOnce(true)
-                .setSmallIcon(R.drawable.ic_notify_dictionary)
-                .getNotification();
+                .setSmallIcon(R.drawable.ic_notify_dictionary);
+        NotificationCompatUtils.setColor(builder,
+                context.getResources().getColor(R.color.notification_accent_color));
+        NotificationCompatUtils.setPriorityToLow(builder);
+        NotificationCompatUtils.setVisibilityToSecret(builder);
+        NotificationCompatUtils.setCategoryToRecommendation(builder);
+        final Notification notification = NotificationCompatUtils.build(builder);
         notificationManager.notify(DICT_AVAILABLE_NOTIFICATION_ID, notification);
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 3743d26..05334c7 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -108,11 +108,23 @@
     private final MoreKeySpec[] mMoreKeys;
     /** More keys column number and flags */
     private final int mMoreKeysColumnAndFlags;
-    private static final int MORE_KEYS_COLUMN_MASK = 0x000000ff;
-    private static final int MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER = 0x80000000;
+    private static final int MORE_KEYS_COLUMN_NUMBER_MASK = 0x000000ff;
+    // If this flag is specified, more keys keyboard should have the specified number of columns.
+    // Otherwise more keys keyboard should have less than or equal to the specified maximum number
+    // of columns.
+    private static final int MORE_KEYS_FLAGS_FIXED_COLUMN = 0x00000100;
+    // If this flag is specified, the order of more keys is determined by the order in the more
+    // keys' specification. Otherwise the order of more keys is automatically determined.
+    private static final int MORE_KEYS_FLAGS_FIXED_ORDER = 0x00000200;
+    private static final int MORE_KEYS_MODE_MAX_COLUMN_WITH_AUTO_ORDER = 0;
+    private static final int MORE_KEYS_MODE_FIXED_COLUMN_WITH_AUTO_ORDER =
+            MORE_KEYS_FLAGS_FIXED_COLUMN;
+    private static final int MORE_KEYS_MODE_FIXED_COLUMN_WITH_FIXED_ORDER =
+            (MORE_KEYS_FLAGS_FIXED_COLUMN | MORE_KEYS_FLAGS_FIXED_ORDER);
     private static final int MORE_KEYS_FLAGS_HAS_LABELS = 0x40000000;
     private static final int MORE_KEYS_FLAGS_NEEDS_DIVIDERS = 0x20000000;
     private static final int MORE_KEYS_FLAGS_NO_PANEL_AUTO_MORE_KEY = 0x10000000;
+    // TODO: Rename these specifiers to !autoOrder! and !fixedOrder! respectively.
     private static final String MORE_KEYS_AUTO_COLUMN_ORDER = "!autoColumnOrder!";
     private static final String MORE_KEYS_FIXED_COLUMN_ORDER = "!fixedColumnOrder!";
     private static final String MORE_KEYS_HAS_LABELS = "!hasLabels!";
@@ -255,25 +267,31 @@
         int actionFlags = style.getFlags(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
         String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
 
-        int moreKeysColumn = style.getInt(keyAttr,
-                R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMoreKeysKeyboardColumn);
+        // Get maximum column order number and set a relevant mode value.
+        int moreKeysColumnAndFlags = MORE_KEYS_MODE_MAX_COLUMN_WITH_AUTO_ORDER
+                | style.getInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn,
+                        params.mMaxMoreKeysKeyboardColumn);
         int value;
         if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_AUTO_COLUMN_ORDER, -1)) > 0) {
-            moreKeysColumn = value & MORE_KEYS_COLUMN_MASK;
+            // Override with fixed column order number and set a relevant mode value.
+            moreKeysColumnAndFlags = MORE_KEYS_MODE_FIXED_COLUMN_WITH_AUTO_ORDER
+                    | (value & MORE_KEYS_COLUMN_NUMBER_MASK);
         }
         if ((value = MoreKeySpec.getIntValue(moreKeys, MORE_KEYS_FIXED_COLUMN_ORDER, -1)) > 0) {
-            moreKeysColumn = MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER | (value & MORE_KEYS_COLUMN_MASK);
+            // Override with fixed column order number and set a relevant mode value.
+            moreKeysColumnAndFlags = MORE_KEYS_MODE_FIXED_COLUMN_WITH_FIXED_ORDER
+                    | (value & MORE_KEYS_COLUMN_NUMBER_MASK);
         }
         if (MoreKeySpec.getBooleanValue(moreKeys, MORE_KEYS_HAS_LABELS)) {
-            moreKeysColumn |= MORE_KEYS_FLAGS_HAS_LABELS;
+            moreKeysColumnAndFlags |= MORE_KEYS_FLAGS_HAS_LABELS;
         }
         if (MoreKeySpec.getBooleanValue(moreKeys, MORE_KEYS_NEEDS_DIVIDERS)) {
-            moreKeysColumn |= MORE_KEYS_FLAGS_NEEDS_DIVIDERS;
+            moreKeysColumnAndFlags |= MORE_KEYS_FLAGS_NEEDS_DIVIDERS;
         }
         if (MoreKeySpec.getBooleanValue(moreKeys, MORE_KEYS_NO_PANEL_AUTO_MORE_KEY)) {
-            moreKeysColumn |= MORE_KEYS_FLAGS_NO_PANEL_AUTO_MORE_KEY;
+            moreKeysColumnAndFlags |= MORE_KEYS_FLAGS_NO_PANEL_AUTO_MORE_KEY;
         }
-        mMoreKeysColumnAndFlags = moreKeysColumn;
+        mMoreKeysColumnAndFlags = moreKeysColumnAndFlags;
 
         final String[] additionalMoreKeys;
         if ((mLabelFlags & LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS) != 0) {
@@ -680,12 +698,16 @@
                 && !TextUtils.isEmpty(mHintLabel);
     }
 
-    public final int getMoreKeysColumn() {
-        return mMoreKeysColumnAndFlags & MORE_KEYS_COLUMN_MASK;
+    public final int getMoreKeysColumnNumber() {
+        return mMoreKeysColumnAndFlags & MORE_KEYS_COLUMN_NUMBER_MASK;
     }
 
-    public final boolean isFixedColumnOrderMoreKeys() {
-        return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER) != 0;
+    public final boolean isMoreKeysFixedColumn() {
+        return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_FIXED_COLUMN) != 0;
+    }
+
+    public final boolean isMoreKeysFixedOrder() {
+        return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_FIXED_ORDER) != 0;
     }
 
     public final boolean hasLabelsInMoreKeys() {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index 0804ceb..3f43673 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -119,7 +119,15 @@
                 new SparseArray<>();
     }
 
-    public static void clearKeyboardCache() {
+    public static void onSystemLocaleChanged() {
+        clearKeyboardCache();
+    }
+
+    public static void onKeyboardThemeChanged() {
+        clearKeyboardCache();
+    }
+
+    private static void clearKeyboardCache() {
         sKeyboardCache.clear();
         sKeysCache.clear();
     }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 30bd1df..389d58a 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -103,7 +103,7 @@
         if (mThemeContext == null || !keyboardTheme.equals(mKeyboardTheme)) {
             mKeyboardTheme = keyboardTheme;
             mThemeContext = new ContextThemeWrapper(context, keyboardTheme.mStyleId);
-            KeyboardLayoutSet.clearKeyboardCache();
+            KeyboardLayoutSet.onKeyboardThemeChanged();
             return true;
         }
         return false;
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
index e0184d7..52e2e85 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
@@ -43,7 +43,7 @@
 
     @UsedForTesting
     static class MoreKeysKeyboardParams extends KeyboardParams {
-        public boolean mIsFixedOrder;
+        public boolean mIsMoreKeysFixedOrder;
         /* package */int mTopRowAdjustment;
         public int mNumRows;
         public int mNumColumns;
@@ -61,29 +61,35 @@
          * Set keyboard parameters of more keys keyboard.
          *
          * @param numKeys number of keys in this more keys keyboard.
-         * @param maxColumns number of maximum columns of this more keys keyboard.
+         * @param numColumn number of columns of this more keys keyboard.
          * @param keyWidth more keys keyboard key width in pixel, including horizontal gap.
          * @param rowHeight more keys keyboard row height in pixel, including vertical gap.
          * @param coordXInParent coordinate x of the key preview in parent keyboard.
          * @param parentKeyboardWidth parent keyboard width in pixel.
-         * @param isFixedColumnOrder if true, more keys should be laid out in fixed order.
+         * @param isMoreKeysFixedColumn true if more keys keyboard should have
+         *   <code>numColumn</code> columns. Otherwise more keys keyboard should have
+         *   <code>numColumn</code> columns at most.
+         * @param isMoreKeysFixedOrder true if the order of more keys is determined by the order in
+         *   the more keys' specification. Otherwise the order of more keys is automatically
+         *   determined.
          * @param dividerWidth width of divider, zero for no dividers.
          */
-        public void setParameters(final int numKeys, final int maxColumns, final int keyWidth,
+        public void setParameters(final int numKeys, final int numColumn, final int keyWidth,
                 final int rowHeight, final int coordXInParent, final int parentKeyboardWidth,
-                final boolean isFixedColumnOrder, final int dividerWidth) {
-            mIsFixedOrder = isFixedColumnOrder;
-            if (parentKeyboardWidth / keyWidth < Math.min(numKeys, maxColumns)) {
+                final boolean isMoreKeysFixedColumn, final boolean isMoreKeysFixedOrder,
+                final int dividerWidth) {
+            mIsMoreKeysFixedOrder = isMoreKeysFixedOrder;
+            if (parentKeyboardWidth / keyWidth < Math.min(numKeys, numColumn)) {
                 throw new IllegalArgumentException("Keyboard is too small to hold more keys: "
-                        + parentKeyboardWidth + " " + keyWidth + " " + numKeys + " " + maxColumns);
+                        + parentKeyboardWidth + " " + keyWidth + " " + numKeys + " " + numColumn);
             }
             mDefaultKeyWidth = keyWidth;
             mDefaultRowHeight = rowHeight;
 
-            final int numRows = (numKeys + maxColumns - 1) / maxColumns;
+            final int numRows = (numKeys + numColumn - 1) / numColumn;
             mNumRows = numRows;
-            final int numColumns = mIsFixedOrder ? Math.min(numKeys, maxColumns)
-                    : getOptimizedColumns(numKeys, maxColumns);
+            final int numColumns = isMoreKeysFixedColumn ? Math.min(numKeys, numColumn)
+                    : getOptimizedColumns(numKeys, numColumn);
             mNumColumns = numColumns;
             final int topKeys = numKeys % numColumns;
             mTopKeys = topKeys == 0 ? numColumns : topKeys;
@@ -120,7 +126,7 @@
             mRightKeys = rightKeys;
 
             // Adjustment of the top row.
-            mTopRowAdjustment = mIsFixedOrder ? getFixedOrderTopRowAdjustment()
+            mTopRowAdjustment = isMoreKeysFixedOrder ? getFixedOrderTopRowAdjustment()
                     : getAutoOrderTopRowAdjustment();
             mDividerWidth = dividerWidth;
             mColumnWidth = mDefaultKeyWidth + mDividerWidth;
@@ -148,7 +154,7 @@
 
         // Return key position according to column count (0 is default).
         /* package */int getColumnPos(final int n) {
-            return mIsFixedOrder ? getFixedOrderColumnPos(n) : getAutomaticColumnPos(n);
+            return mIsMoreKeysFixedOrder ? getFixedOrderColumnPos(n) : getAutomaticColumnPos(n);
         }
 
         private int getFixedOrderColumnPos(final int n) {
@@ -263,7 +269,8 @@
          * @param keyboard the {@link Keyboard} that contains the parentKey.
          * @param isSingleMoreKeyWithPreview true if the <code>key</code> has just a single
          *        "more key" and its key popup preview is enabled.
-         * @param keyPreviewDrawParams the parameter to place key preview.
+         * @param keyPreviewVisibleWidth the width of visible part of key popup preview.
+         * @param keyPreviewVisibleHeight the height of visible part of key popup preview
          * @param paintToMeasure the {@link Paint} object to measure a "more key" width
          */
         public Builder(final Context context, final Key key, final Keyboard keyboard,
@@ -306,9 +313,9 @@
                 dividerWidth = 0;
             }
             final MoreKeySpec[] moreKeys = key.getMoreKeys();
-            mParams.setParameters(moreKeys.length, key.getMoreKeysColumn(), keyWidth, rowHeight,
+            mParams.setParameters(moreKeys.length, key.getMoreKeysColumnNumber(), keyWidth, rowHeight,
                     key.getX() + key.getWidth() / 2, keyboard.mId.mWidth,
-                    key.isFixedColumnOrderMoreKeys(), dividerWidth);
+                    key.isMoreKeysFixedColumn(), key.isMoreKeysFixedOrder(), dividerWidth);
         }
 
         private static int getMaxKeyWidth(final Key parentKey, final int minKeyWidth,
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d3dde6f..a05b82c 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -93,6 +93,7 @@
 import com.android.inputmethod.latin.utils.JniUtils;
 import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
 import com.android.inputmethod.latin.utils.StatsUtils;
+import com.android.inputmethod.latin.utils.StatsUtilsManager;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 import com.android.inputmethod.latin.utils.ViewLayoutUtils;
 
@@ -157,6 +158,7 @@
     private final SubtypeSwitcher mSubtypeSwitcher;
     private final SubtypeState mSubtypeState = new SubtypeState();
     private final SpecialKeyDetector mSpecialKeyDetector;
+    private StatsUtilsManager mStatsUtilsManager;
 
     // Object for reacting to adding/removing a dictionary pack.
     private final BroadcastReceiver mDictionaryPackInstallReceiver =
@@ -537,6 +539,7 @@
         mSubtypeSwitcher = SubtypeSwitcher.getInstance();
         mKeyboardSwitcher = KeyboardSwitcher.getInstance();
         mSpecialKeyDetector = new SpecialKeyDetector(this);
+        mStatsUtilsManager = StatsUtilsManager.getInstance();
         mIsHardwareAcceleratedDrawingEnabled =
                 InputMethodServiceCompatUtils.enableHardwareAcceleration(this);
         Log.i(TAG, "Hardware accelerated drawing: " + mIsHardwareAcceleratedDrawingEnabled);
@@ -552,8 +555,6 @@
         KeyboardSwitcher.init(this);
         AudioAndHapticFeedbackManager.init(this);
         AccessibilityUtils.init(this);
-        StatsUtils.init(this);
-
         super.onCreate();
 
         mHandler.onCreate();
@@ -585,7 +586,7 @@
         registerReceiver(mDictionaryDumpBroadcastReceiver, dictDumpFilter);
 
         DictionaryDecayBroadcastReciever.setUpIntervalAlarmForDictionaryDecaying(this);
-
+        mStatsUtilsManager.onCreate(this /* context */);
         StatsUtils.onCreate(mSettings.getCurrent(), mRichImm);
     }
 
@@ -608,7 +609,7 @@
         mDictionaryFacilitator.updateEnabledSubtypes(mRichImm.getMyEnabledInputMethodSubtypeList(
                 true /* allowsImplicitlySelectedSubtypes */));
         refreshPersonalizationDictionarySession(currentSettingsValues);
-        StatsUtils.onLoadSettings(currentSettingsValues);
+        mStatsUtilsManager.onLoadSettings(currentSettingsValues);
     }
 
     private void refreshPersonalizationDictionarySession(
@@ -698,7 +699,7 @@
         unregisterReceiver(mConnectivityAndRingerModeChangeReceiver);
         unregisterReceiver(mDictionaryPackInstallReceiver);
         unregisterReceiver(mDictionaryDumpBroadcastReceiver);
-        StatsUtils.onDestroy();
+        mStatsUtilsManager.onDestroy();
         super.onDestroy();
     }
 
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 1eebabe..6bc3da8 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -429,7 +429,7 @@
      */
     @UsedForTesting
     public SuggestedWordInfo getTypedWordInfoOrNull() {
-        if (this == EMPTY) {
+        if (SuggestedWords.INDEX_OF_TYPED_WORD >= size()) {
             return null;
         }
         final SuggestedWordInfo info = getInfo(SuggestedWords.INDEX_OF_TYPED_WORD);
diff --git a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java
index e4ee426..123ab20 100644
--- a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java
+++ b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java
@@ -17,21 +17,16 @@
 package com.android.inputmethod.latin;
 
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
 import android.os.Process;
-import android.preference.PreferenceManager;
 import android.util.Log;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.compat.IntentCompatUtils;
-import com.android.inputmethod.latin.settings.Settings;
+import com.android.inputmethod.keyboard.KeyboardLayoutSet;
 import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager;
-import com.android.inputmethod.latin.setup.SetupActivity;
 import com.android.inputmethod.latin.utils.UncachedInputMethodManagerUtils;
 
 /**
@@ -58,6 +53,9 @@
  * When a multiuser account has been created, {@link Intent#ACTION_USER_INITIALIZE} is received
  * by this receiver and it checks the whether the setup wizard's icon should be appeared or not on
  * the launcher depending on which partition this IME is installed.
+ *
+ * When the system locale has been changed, {@link Intent#ACTION_LOCALE_CHANGED} is received by
+ * this receiver and the {@link KeyboardLayoutSet}'s cache is cleared.
  */
 public final class SystemBroadcastReceiver extends BroadcastReceiver {
     private static final String TAG = SystemBroadcastReceiver.class.getSimpleName();
@@ -67,21 +65,22 @@
         final String intentAction = intent.getAction();
         if (Intent.ACTION_MY_PACKAGE_REPLACED.equals(intentAction)) {
             Log.i(TAG, "Package has been replaced: " + context.getPackageName());
-        } else if (Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) {
-            Log.i(TAG, "Boot has been completed");
-        } else if (IntentCompatUtils.is_ACTION_USER_INITIALIZE(intentAction)) {
-            Log.i(TAG, "User initialize");
-        }
-
-        LauncherIconVisibilityManager.onReceiveGlobalIntent(intentAction, context);
-
-        if (Intent.ACTION_MY_PACKAGE_REPLACED.equals(intentAction)) {
             // Need to restore additional subtypes because system always clears additional
             // subtypes when the package is replaced.
             RichInputMethodManager.init(context);
             final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
             final InputMethodSubtype[] additionalSubtypes = richImm.getAdditionalSubtypes(context);
             richImm.setAdditionalInputMethodSubtypes(additionalSubtypes);
+            LauncherIconVisibilityManager.updateSetupWizardIconVisibility(context);
+        } else if (Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) {
+            Log.i(TAG, "Boot has been completed");
+            LauncherIconVisibilityManager.updateSetupWizardIconVisibility(context);
+        } else if (IntentCompatUtils.is_ACTION_USER_INITIALIZE(intentAction)) {
+            Log.i(TAG, "User initialize");
+            LauncherIconVisibilityManager.updateSetupWizardIconVisibility(context);
+        } else if (Intent.ACTION_LOCALE_CHANGED.equals(intentAction)) {
+            Log.i(TAG, "System locale changed");
+            KeyboardLayoutSet.onSystemLocaleChanged();
         }
 
         // The process that hosts this broadcast receiver is invoked and remains alive even after
diff --git a/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
index 6d7f53c..d53a616 100644
--- a/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
@@ -30,11 +30,14 @@
 import android.preference.Preference;
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceGroup;
+import android.support.v4.view.ViewCompat;
 import android.util.Pair;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 import android.widget.ArrayAdapter;
@@ -43,6 +46,7 @@
 import android.widget.Toast;
 
 import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
+import com.android.inputmethod.compat.ViewCompatUtils;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
@@ -233,6 +237,12 @@
             mSubtypeLocaleSpinner.setAdapter(mProxy.getSubtypeLocaleAdapter());
             mKeyboardLayoutSetSpinner = (Spinner) v.findViewById(R.id.keyboard_layout_set_spinner);
             mKeyboardLayoutSetSpinner.setAdapter(mProxy.getKeyboardLayoutSetAdapter());
+            // All keyboard layout names are in the Latin script and thus left to right. That means
+            // the view would align them to the left even if the system locale is RTL, but that
+            // would look strange. To fix this, we align them to the view's start, which will be
+            // natural for any direction.
+            ViewCompatUtils.setTextAlignment(
+                    mKeyboardLayoutSetSpinner, ViewCompatUtils.TEXT_ALIGNMENT_VIEW_START);
             return v;
         }
 
@@ -398,6 +408,16 @@
     }
 
     @Override
+    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+            final Bundle savedInstanceState) {
+        final View view = super.onCreateView(inflater, container, savedInstanceState);
+        // For correct display in RTL locales, we need to set the layout direction of the
+        // fragment's top view.
+        ViewCompat.setLayoutDirection(view, ViewCompat.LAYOUT_DIRECTION_LOCALE);
+        return view;
+    }
+
+    @Override
     public void onActivityCreated(final Bundle savedInstanceState) {
         final Context context = getActivity();
         mSubtypeLocaleAdapter = new SubtypeLocaleAdapter(context);
@@ -422,7 +442,7 @@
                     KEY_SUBTYPE_FOR_SUBTYPE_ENABLER);
             final SubtypePreference subtypePref = (SubtypePreference)findPreference(
                     mSubtypePreferenceKeyForSubtypeEnabler);
-            mSubtypeEnablerNotificationDialog = createDialog(subtypePref);
+            mSubtypeEnablerNotificationDialog = createDialog();
             mSubtypeEnablerNotificationDialog.show();
         }
     }
@@ -476,7 +496,7 @@
             if (findDuplicatedSubtype(subtype) == null) {
                 mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
                 mSubtypePreferenceKeyForSubtypeEnabler = subtypePref.getKey();
-                mSubtypeEnablerNotificationDialog = createDialog(subtypePref);
+                mSubtypeEnablerNotificationDialog = createDialog();
                 mSubtypeEnablerNotificationDialog.show();
                 return;
             }
@@ -513,7 +533,7 @@
                 localeString, keyboardLayoutSetName);
     }
 
-    private AlertDialog createDialog(final SubtypePreference subtypePref) {
+    private AlertDialog createDialog() {
         final AlertDialog.Builder builder = new AlertDialog.Builder(
                 DialogUtils.getPlatformDialogThemeContext(getActivity()));
         builder.setTitle(R.string.custom_input_styles_title)
diff --git a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
index 9585736..3f0b102 100644
--- a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
+++ b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
@@ -24,7 +24,6 @@
 import android.preference.PreferenceManager;
 import android.util.Log;
 
-import com.android.inputmethod.compat.IntentCompatUtils;
 import com.android.inputmethod.latin.settings.Settings;
 
 /**
@@ -55,14 +54,6 @@
 public final class LauncherIconVisibilityManager {
     private static final String TAG = LauncherIconVisibilityManager.class.getSimpleName();
 
-    public static void onReceiveGlobalIntent(final String action, final Context context) {
-        if (Intent.ACTION_MY_PACKAGE_REPLACED.equals(action) ||
-                Intent.ACTION_BOOT_COMPLETED.equals(action) ||
-                IntentCompatUtils.is_ACTION_USER_INITIALIZE(action)) {
-            updateSetupWizardIconVisibility(context);
-        }
-    }
-
     public static void updateSetupWizardIconVisibility(final Context context) {
         final ComponentName setupWizardActivity = new ComponentName(context, SetupActivity.class);
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
diff --git a/native/jni/NativeFileList.mk b/native/jni/NativeFileList.mk
index 018a34d..082e1e2 100644
--- a/native/jni/NativeFileList.mk
+++ b/native/jni/NativeFileList.mk
@@ -121,10 +121,12 @@
 
 LATIN_IME_CORE_TEST_FILES := \
     defines_test.cpp \
-    suggest/core/layout/normal_distribution_2d_test.cpp \
+    suggest/core/dicnode/dic_node_pool_test.cpp \
     suggest/core/dictionary/bloom_filter_test.cpp \
+    suggest/core/layout/normal_distribution_2d_test.cpp \
     suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp \
     suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp \
+    suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table_test.cpp \
     suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer_test.cpp \
     suggest/policyimpl/dictionary/utils/byte_array_utils_test.cpp \
     suggest/policyimpl/dictionary/utils/sparse_table_test.cpp \
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
index cf238ee..2bdf077 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
@@ -34,7 +34,7 @@
 bool TerminalPositionLookupTable::setTerminalPtNodePosition(
         const int terminalId, const int terminalPtNodePos) {
     if (terminalId < 0) {
-        return NOT_A_DICT_POS;
+        return false;
     }
     while (terminalId >= mSize) {
         // Write new entry.
diff --git a/native/jni/tests/suggest/core/dicnode/dic_node_pool_test.cpp b/native/jni/tests/suggest/core/dicnode/dic_node_pool_test.cpp
new file mode 100644
index 0000000..854efdf
--- /dev/null
+++ b/native/jni/tests/suggest/core/dicnode/dic_node_pool_test.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "suggest/core/dicnode/dic_node_pool.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace {
+
+TEST(DicNodePoolTest, TestGet) {
+    static const int CAPACITY = 10;
+    DicNodePool dicNodePool(CAPACITY);
+
+    for (int i = 0; i < CAPACITY; ++i) {
+        EXPECT_NE(nullptr, dicNodePool.getInstance());
+    }
+    EXPECT_EQ(nullptr, dicNodePool.getInstance());
+}
+
+TEST(DicNodePoolTest, TestPlaceBack) {
+    static const int CAPACITY = 1;
+    DicNodePool dicNodePool(CAPACITY);
+
+    DicNode *const dicNode = dicNodePool.getInstance();
+    EXPECT_NE(nullptr, dicNode);
+    EXPECT_EQ(nullptr, dicNodePool.getInstance());
+    dicNodePool.placeBackInstance(dicNode);
+    EXPECT_EQ(dicNode, dicNodePool.getInstance());
+}
+
+TEST(DicNodePoolTest, TestReset) {
+    static const int CAPACITY_SMALL = 2;
+    static const int CAPACITY_LARGE = 10;
+    DicNodePool dicNodePool(CAPACITY_SMALL);
+
+    for (int i = 0; i < CAPACITY_SMALL; ++i) {
+        EXPECT_NE(nullptr, dicNodePool.getInstance());
+    }
+    EXPECT_EQ(nullptr, dicNodePool.getInstance());
+
+    dicNodePool.reset(CAPACITY_LARGE);
+    for (int i = 0; i < CAPACITY_LARGE; ++i) {
+        EXPECT_NE(nullptr, dicNodePool.getInstance());
+    }
+    EXPECT_EQ(nullptr, dicNodePool.getInstance());
+
+    dicNodePool.reset(CAPACITY_SMALL);
+    for (int i = 0; i < CAPACITY_SMALL; ++i) {
+        EXPECT_NE(nullptr, dicNodePool.getInstance());
+    }
+    EXPECT_EQ(nullptr, dicNodePool.getInstance());
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table_test.cpp
new file mode 100644
index 0000000..23b9c55
--- /dev/null
+++ b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table_test.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
+
+namespace latinime {
+namespace {
+
+TEST(TerminalPositionLookupTableTest, TestGetFromEmptyTable) {
+    TerminalPositionLookupTable lookupTable;
+
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(0));
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(-1));
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(
+            Ver4DictConstants::NOT_A_TERMINAL_ID));
+}
+
+TEST(TerminalPositionLookupTableTest, TestSetAndGet) {
+    TerminalPositionLookupTable lookupTable;
+
+    EXPECT_TRUE(lookupTable.setTerminalPtNodePosition(10, 100));
+    EXPECT_EQ(100, lookupTable.getTerminalPtNodePosition(10));
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(9));
+    EXPECT_TRUE(lookupTable.setTerminalPtNodePosition(9, 200));
+    EXPECT_EQ(200, lookupTable.getTerminalPtNodePosition(9));
+    EXPECT_TRUE(lookupTable.setTerminalPtNodePosition(10, 300));
+    EXPECT_EQ(300, lookupTable.getTerminalPtNodePosition(10));
+    EXPECT_FALSE(lookupTable.setTerminalPtNodePosition(-1, 400));
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(-1));
+    EXPECT_FALSE(lookupTable.setTerminalPtNodePosition(Ver4DictConstants::NOT_A_TERMINAL_ID, 500));
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(
+            Ver4DictConstants::NOT_A_TERMINAL_ID));
+}
+
+TEST(TerminalPositionLookupTableTest, TestGC) {
+    TerminalPositionLookupTable lookupTable;
+
+    const std::vector<int> terminalIds = { 10, 20, 30 };
+    const std::vector<int> terminalPositions = { 100, 200, 300 };
+
+    for (size_t i = 0; i < terminalIds.size(); ++i) {
+        EXPECT_TRUE(lookupTable.setTerminalPtNodePosition(terminalIds[i], terminalPositions[i]));
+    }
+
+    TerminalPositionLookupTable::TerminalIdMap terminalIdMap;
+    EXPECT_TRUE(lookupTable.runGCTerminalIds(&terminalIdMap));
+
+    for (size_t i = 0; i < terminalIds.size(); ++i) {
+        EXPECT_EQ(static_cast<int>(i), terminalIdMap[terminalIds[i]])
+                << "Terminal id (" << terminalIds[i] << ") should be changed to " << i;
+        EXPECT_EQ(terminalPositions[i], lookupTable.getTerminalPtNodePosition(i));
+    }
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java
index 96f9255..9e795db 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java
@@ -18,34 +18,33 @@
 
 import android.content.res.Resources;
 import android.test.suitebuilder.annotation.MediumTest;
-import android.text.InputType;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
 import com.android.inputmethod.latin.utils.RunInLocale;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
+import java.util.Locale;
+
 @MediumTest
-public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetTestsBase {
+public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActionLabelLxxTests {
     @Override
     protected int getKeyboardThemeForTests() {
         return KeyboardTheme.THEME_ID_KLP;
     }
 
-    private static void doTestActionKey(final String tag, final KeyboardLayoutSet layoutSet,
-            final int elementId, final CharSequence label, final int iconId) {
-        final Keyboard keyboard = layoutSet.getKeyboard(elementId);
-        final Key enterKey = keyboard.getKey(Constants.CODE_ENTER);
-        assertNotNull(tag + " enter key on " + keyboard.mId, enterKey);
-        assertEquals(tag + " enter label " + enterKey, label, enterKey.getLabel());
-        assertEquals(tag + " enter icon " + enterKey, iconId, enterKey.getIconId());
+    protected void doTestActionKeyLabel(final String tag, final InputMethodSubtype subtype,
+            final int actionId, final int labelResId) {
+        final Locale labelLocale = subtype.getLocale().equals(SubtypeLocaleUtils.NO_LANGUAGE)
+                ? null : SubtypeLocaleUtils.getSubtypeLocale(subtype);
+        doTestActionKeyLabel(tag, subtype, actionId, labelLocale, labelResId);
     }
 
-    protected void doTestActionLabel(final String tag, final InputMethodSubtype subtype,
-            final int actionId, final int labelResId) {
+    protected void doTestActionKeyLabel(final String tag, final InputMethodSubtype subtype,
+            final int actionId, final Locale labelLocale, final int labelResId) {
         final EditorInfo editorInfo = new EditorInfo();
         editorInfo.imeOptions = actionId;
         final RunInLocale<String> job = new RunInLocale<String>() {
@@ -54,138 +53,127 @@
                 return res.getString(labelResId);
             }
         };
-        final Resources res = getContext().getResources();
-        final String label;
-        if (subtype.getLocale().equals(SubtypeLocaleUtils.NO_LANGUAGE)) {
-            // Using system locale.
-            label = res.getString(labelResId);
-        } else {
-            label = job.runInLocale(res, SubtypeLocaleUtils.getSubtypeLocale(subtype));
-        }
-        doTestActionLabel(tag, subtype, editorInfo, label);
+        final String label = job.runInLocale(getContext().getResources(), labelLocale);
+        doTestActionKeyLabel(tag, subtype, editorInfo, label);
     }
 
-    protected void doTestActionLabel(final String tag, final InputMethodSubtype subtype,
-            final EditorInfo editorInfo, final CharSequence label) {
-        // Test text layouts.
-        editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
-        final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        // Test phone number layouts.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        // Test normal number layout.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        // Test number password layouts.
-        editorInfo.inputType =
-                InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
-        final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-    }
-
-    protected void doTestActionKeyIcon(final String tag, final InputMethodSubtype subtype,
-            final int actionId, final String iconName) {
-        final int iconId = KeyboardIconsSet.getIconId(iconName);
-        final EditorInfo editorInfo = new EditorInfo();
-        editorInfo.imeOptions = actionId;
-        // Test text layouts.
-        editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
-        final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET, null /* label */, iconId);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS, null /* label */, iconId);
-        doTestActionKey(
-                tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED, null /* label */, iconId);
-        // Test phone number layouts.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE, null /* label */, iconId);
-        doTestActionKey(
-                tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS, null /* label */, iconId);
-        // Test normal number layout.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER, null /* label */, iconId);
-        // Test number password layout.
-        editorInfo.inputType =
-                InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
-        final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER, null /* label */, iconId);
-    }
-
+    @Override
     public void testActionUnspecified() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "unspecifiled "
-                    + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_UNSPECIFIED,
-                    KeyboardIconsSet.NAME_ENTER_KEY);
-        }
+        super.testActionUnspecified();
     }
 
+    @Override
     public void testActionNone() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "none " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_NONE,
-                    KeyboardIconsSet.NAME_ENTER_KEY);
-        }
+        super.testActionNone();
     }
 
+    @Override
     public void testActionGo() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "go " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionLabel(tag, subtype, EditorInfo.IME_ACTION_GO, R.string.label_go_key);
+            doTestActionKeyLabel(tag, subtype, EditorInfo.IME_ACTION_GO, R.string.label_go_key);
         }
     }
 
+    @Override
     public void testActionSearch() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "search " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_SEARCH,
-                    KeyboardIconsSet.NAME_SEARCH_KEY);
-        }
+        super.testActionSearch();
     }
 
+    @Override
     public void testActionSend() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "send " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionLabel(tag, subtype, EditorInfo.IME_ACTION_SEND, R.string.label_send_key);
+            doTestActionKeyLabel(tag, subtype, EditorInfo.IME_ACTION_SEND, R.string.label_send_key);
         }
     }
 
+    @Override
     public void testActionNext() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "next " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionLabel(tag, subtype, EditorInfo.IME_ACTION_NEXT, R.string.label_next_key);
+            doTestActionKeyLabel(tag, subtype, EditorInfo.IME_ACTION_NEXT, R.string.label_next_key);
         }
     }
 
+    @Override
     public void testActionDone() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "done " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionLabel(tag, subtype, EditorInfo.IME_ACTION_DONE, R.string.label_done_key);
+            doTestActionKeyLabel(tag, subtype, EditorInfo.IME_ACTION_DONE, R.string.label_done_key);
         }
     }
 
+    @Override
     public void testActionPrevious() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "previous " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionLabel(
+            doTestActionKeyLabel(
                     tag, subtype, EditorInfo.IME_ACTION_PREVIOUS, R.string.label_previous_key);
         }
     }
 
+    @Override
     public void testActionCustom() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "custom " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            final CharSequence customLabel = "customLabel";
-            final EditorInfo editorInfo = new EditorInfo();
-            editorInfo.imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED;
-            editorInfo.actionLabel = customLabel;
-            doTestActionLabel(tag, subtype, editorInfo, customLabel);
+        super.testActionCustom();
+    }
+
+    // Working variable to simulate system locale changing.
+    private Locale mSystemLocale = Locale.getDefault();
+
+    private void doTestActionLabelInLocale(final InputMethodSubtype subtype,
+            final Locale labelLocale, final Locale systemLocale) {
+        // Simulate system locale changing, see {@link SystemBroadcastReceiver}.
+        if (!systemLocale.equals(mSystemLocale)) {
+            KeyboardLayoutSet.onSystemLocaleChanged();
+            mSystemLocale = systemLocale;
         }
+        final String tag = "label=" + labelLocale + " system=" + systemLocale
+                + " " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+        final RunInLocale<Void> job = new RunInLocale<Void>() {
+            @Override
+            public Void job(final Resources res) {
+                doTestActionKeyIcon(tag + " unspecified", subtype,
+                        EditorInfo.IME_ACTION_UNSPECIFIED, KeyboardIconsSet.NAME_ENTER_KEY);
+                doTestActionKeyIcon(tag + " none", subtype,
+                        EditorInfo.IME_ACTION_NONE, KeyboardIconsSet.NAME_ENTER_KEY);
+                doTestActionKeyLabel(tag + " go", subtype,
+                        EditorInfo.IME_ACTION_GO, labelLocale, R.string.label_go_key);
+                doTestActionKeyIcon(tag + " search", subtype,
+                        EditorInfo.IME_ACTION_SEARCH, KeyboardIconsSet.NAME_SEARCH_KEY);
+                doTestActionKeyLabel(tag + " send", subtype,
+                        EditorInfo.IME_ACTION_SEND, labelLocale, R.string.label_send_key);
+                doTestActionKeyLabel(tag + " next", subtype,
+                        EditorInfo.IME_ACTION_NEXT, labelLocale, R.string.label_next_key);
+                doTestActionKeyLabel(tag + " done", subtype,
+                        EditorInfo.IME_ACTION_DONE, labelLocale, R.string.label_done_key);
+                doTestActionKeyLabel(tag + " previous", subtype,
+                        EditorInfo.IME_ACTION_PREVIOUS, labelLocale, R.string.label_previous_key);
+                return null;
+            }
+        };
+        job.runInLocale(getContext().getResources(), systemLocale);
+    }
+
+    public void testActionLabelInOtherLocale() {
+        final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
+        final InputMethodSubtype italian = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                Locale.ITALIAN.toString(), SubtypeLocaleUtils.QWERTY);
+        // An action label should be displayed in subtype's locale regardless of the system locale.
+        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.US);
+        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.FRENCH);
+        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.ITALIAN);
+        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.JAPANESE);
+    }
+
+    public void testNoLanguageSubtypeActionLabel() {
+        final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
+        final InputMethodSubtype noLanguage = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
+        // An action label of no language keyboard should be displayed in the system locale.
+        doTestActionLabelInLocale(noLanguage, Locale.US, Locale.US);
+        doTestActionLabelInLocale(noLanguage, Locale.FRENCH, Locale.FRENCH);
+        doTestActionLabelInLocale(noLanguage, Locale.ITALIAN, Locale.ITALIAN);
+        doTestActionLabelInLocale(noLanguage, Locale.JAPANESE, Locale.JAPANESE);
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java
index 7747ac5..25da509 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java
@@ -17,30 +17,99 @@
 package com.android.inputmethod.keyboard;
 
 import android.test.suitebuilder.annotation.MediumTest;
+import android.text.InputType;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 @MediumTest
-public class KeyboardLayoutSetActionLabelLxxTests extends KeyboardLayoutSetActionLabelKlpTests {
+public class KeyboardLayoutSetActionLabelLxxTests extends KeyboardLayoutSetTestsBase {
     @Override
     protected int getKeyboardThemeForTests() {
         return KeyboardTheme.THEME_ID_LXX_DARK;
     }
 
-    @Override
+    private static void doTestActionKey(final String tag, final KeyboardLayoutSet layoutSet,
+            final int elementId, final CharSequence label, final int iconId) {
+        final Keyboard keyboard = layoutSet.getKeyboard(elementId);
+        final Key enterKey = keyboard.getKey(Constants.CODE_ENTER);
+        assertNotNull(tag + " enter key on " + keyboard.mId, enterKey);
+        assertEquals(tag + " enter label " + enterKey, label, enterKey.getLabel());
+        assertEquals(tag + " enter icon " + enterKey, iconId, enterKey.getIconId());
+    }
+
+    protected void doTestActionKeyLabel(final String tag, final InputMethodSubtype subtype,
+            final EditorInfo editorInfo, final CharSequence label) {
+        // Test text layouts.
+        editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+        final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
+        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET,
+                label, KeyboardIconsSet.ICON_UNDEFINED);
+        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS,
+                label, KeyboardIconsSet.ICON_UNDEFINED);
+        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED,
+                label, KeyboardIconsSet.ICON_UNDEFINED);
+        // Test phone number layouts.
+        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE,
+                label, KeyboardIconsSet.ICON_UNDEFINED);
+        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS,
+                label, KeyboardIconsSet.ICON_UNDEFINED);
+        // Test normal number layout.
+        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER,
+                label, KeyboardIconsSet.ICON_UNDEFINED);
+        // Test number password layouts.
+        editorInfo.inputType =
+                InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
+        final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
+        doTestActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER,
+                label, KeyboardIconsSet.ICON_UNDEFINED);
+    }
+
+    protected void doTestActionKeyIcon(final String tag, final InputMethodSubtype subtype,
+            final int actionId, final String iconName) {
+        final int iconId = KeyboardIconsSet.getIconId(iconName);
+        final EditorInfo editorInfo = new EditorInfo();
+        editorInfo.imeOptions = actionId;
+        // Test text layouts.
+        editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+        final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
+        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET, null /* label */, iconId);
+        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS, null /* label */, iconId);
+        doTestActionKey(
+                tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED, null /* label */, iconId);
+        // Test phone number layouts.
+        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE, null /* label */, iconId);
+        doTestActionKey(
+                tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS, null /* label */, iconId);
+        // Test normal number layout.
+        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER, null /* label */, iconId);
+        // Test number password layout.
+        editorInfo.inputType =
+                InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
+        final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
+        doTestActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER, null /* label */, iconId);
+    }
+
     public void testActionUnspecified() {
-        super.testActionUnspecified();
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "unspecifiled "
+                    + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_UNSPECIFIED,
+                    KeyboardIconsSet.NAME_ENTER_KEY);
+        }
     }
 
-    @Override
     public void testActionNone() {
-        super.testActionNone();
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "none " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_NONE,
+                    KeyboardIconsSet.NAME_ENTER_KEY);
+        }
     }
 
-    @Override
     public void testActionGo() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "go " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
@@ -49,12 +118,14 @@
         }
     }
 
-    @Override
     public void testActionSearch() {
-        super.testActionSearch();
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "search " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_SEARCH,
+                    KeyboardIconsSet.NAME_SEARCH_KEY);
+        }
     }
 
-    @Override
     public void testActionSend() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "send " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
@@ -63,7 +134,6 @@
         }
     }
 
-    @Override
     public void testActionNext() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "next " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
@@ -72,7 +142,6 @@
         }
     }
 
-    @Override
     public void testActionDone() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "done " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
@@ -81,7 +150,6 @@
         }
     }
 
-    @Override
     public void testActionPrevious() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "previous " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
@@ -90,8 +158,14 @@
         }
     }
 
-    @Override
     public void testActionCustom() {
-        super.testActionCustom();
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "custom " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            final CharSequence customLabel = "customLabel";
+            final EditorInfo editorInfo = new EditorInfo();
+            editorInfo.imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED;
+            editorInfo.actionLabel = customLabel;
+            doTestActionKeyLabel(tag, subtype, editorInfo, customLabel);
+        }
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java
index 0a76a9d..29aa758 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java
@@ -43,7 +43,6 @@
     private final ArrayList<InputMethodSubtype> mAsciiCapableSubtypesList = new ArrayList<>();
     private final ArrayList<InputMethodSubtype> mAdditionalSubtypesList = new ArrayList<>();
 
-    private Context mThemeContext;
     private int mScreenMetrics;
 
     protected abstract int getKeyboardThemeForTests();
@@ -51,12 +50,13 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mScreenMetrics = mContext.getResources().getInteger(R.integer.config_screen_metrics);
-
         final KeyboardTheme keyboardTheme = KeyboardTheme.searchKeyboardThemeById(
                 getKeyboardThemeForTests());
-        mThemeContext = new ContextThemeWrapper(mContext, keyboardTheme.mStyleId);
-        RichInputMethodManager.init(mThemeContext);
+        setContext(new ContextThemeWrapper(getContext(), keyboardTheme.mStyleId));
+
+        final Context context = getContext();
+        mScreenMetrics = context.getResources().getInteger(R.integer.config_screen_metrics);
+        RichInputMethodManager.init(context);
         final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
 
         final InputMethodInfo imi = richImm.getInputMethodInfoOfThisIme();
@@ -122,7 +122,7 @@
     protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype,
             final EditorInfo editorInfo, final boolean voiceInputKeyEnabled,
             final boolean languageSwitchKeyEnabled) {
-        final Context context = mThemeContext;
+        final Context context = getContext();
         final Resources res = context.getResources();
         final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
         final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res);
diff --git a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderAutoOrderTests.java b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderAutoOrderTests.java
new file mode 100644
index 0000000..ebefe2d
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderAutoOrderTests.java
@@ -0,0 +1,2464 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import com.android.inputmethod.keyboard.MoreKeysKeyboard.MoreKeysKeyboardParams;
+
+@MediumTest
+public class MoreKeysKeyboardBuilderAutoOrderTests extends AndroidTestCase {
+    private static final int WIDTH = 10;
+    private static final int HEIGHT = 10;
+
+    private static final int KEYBOARD_WIDTH = WIDTH * 10;
+    private static final int XPOS_L0 = WIDTH * 0 + WIDTH / 2;
+    private static final int XPOS_L1 = WIDTH * 1 + WIDTH / 2;
+    private static final int XPOS_L2 = WIDTH * 2 + WIDTH / 2;
+    private static final int XPOS_L3 = WIDTH * 3 + WIDTH / 2;
+    private static final int XPOS_M0 = WIDTH * 4 + WIDTH / 2;
+    private static final int XPOS_M1 = WIDTH * 5 + WIDTH / 2;
+    private static final int XPOS_R3 = WIDTH * 6 + WIDTH / 2;
+    private static final int XPOS_R2 = WIDTH * 7 + WIDTH / 2;
+    private static final int XPOS_R1 = WIDTH * 8 + WIDTH / 2;
+    private static final int XPOS_R0 = WIDTH * 9 + WIDTH / 2;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    private static MoreKeysKeyboardParams createParams(final int numKeys, final int columnNum,
+            final int coordXInParent) {
+        final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams();
+        params.setParameters(numKeys, columnNum, WIDTH, HEIGHT, coordXInParent, KEYBOARD_WIDTH,
+                true /* isMoreKeysFixedColumn */, false /* isMoreKeysFixedOrder */,
+                0 /* dividerWidth */);
+        return params;
+    }
+
+    public void testLayoutError() {
+        MoreKeysKeyboardParams params = null;
+        try {
+            final int maxColumns = KEYBOARD_WIDTH / WIDTH;
+            params = createParams(maxColumns + 1, maxColumns + 1, HEIGHT);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Too small keyboard to hold more keys keyboard.
+        }
+        assertNull("Too small keyboard to hold more keys keyboard", params);
+    }
+
+    // More keys keyboard layout test.
+    // "[n]" represents n-th key position in more keys keyboard.
+    // "<1>" is the default key.
+
+    // <1>
+    public void testLayout1KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(1, 5, XPOS_M0);
+        assertEquals("1 key auto 5 M0 columns", 1, params.mNumColumns);
+        assertEquals("1 key auto 5 M0 rows", 1, params.mNumRows);
+        assertEquals("1 key auto 5 M0 left", 0, params.mLeftKeys);
+        assertEquals("1 key auto 5 M0 right", 1, params.mRightKeys);
+        assertEquals("1 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("1 key auto 5 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key auto 5 M0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |<1>
+    public void testLayout1KeyAuto5L0() {
+        MoreKeysKeyboardParams params = createParams(1, 5, XPOS_L0);
+        assertEquals("1 key auto 5 L0 columns", 1, params.mNumColumns);
+        assertEquals("1 key auto 5 L0 rows", 1, params.mNumRows);
+        assertEquals("1 key auto 5 L0 left", 0, params.mLeftKeys);
+        assertEquals("1 key auto 5 L0 right", 1, params.mRightKeys);
+        assertEquals("1 key auto 5 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("1 key auto 5 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key auto 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ <1>
+    public void testLayout1KeyAuto5L1() {
+        MoreKeysKeyboardParams params = createParams(1, 5, XPOS_L1);
+        assertEquals("1 key auto 5 L1 columns", 1, params.mNumColumns);
+        assertEquals("1 key auto 5 L1 rows", 1, params.mNumRows);
+        assertEquals("1 key auto 5 L1 left", 0, params.mLeftKeys);
+        assertEquals("1 key auto 5 L1 right", 1, params.mRightKeys);
+        assertEquals("1 key auto 5 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("1 key auto 5 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key auto 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ <1>
+    public void testLayout1KeyAuto5L2() {
+        MoreKeysKeyboardParams params = createParams(1, 5, XPOS_L2);
+        assertEquals("1 key auto 5 L2 columns", 1, params.mNumColumns);
+        assertEquals("1 key auto 5 L2 rows", 1, params.mNumRows);
+        assertEquals("1 key auto 5 L2 left", 0, params.mLeftKeys);
+        assertEquals("1 key auto 5 L2 right", 1, params.mRightKeys);
+        assertEquals("1 key auto 5 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("1 key auto 5 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key auto 5 L2 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // <1>|
+    public void testLayout1KeyAuto5R0() {
+        MoreKeysKeyboardParams params = createParams(1, 5, XPOS_R0);
+        assertEquals("1 key auto 5 R0 columns", 1, params.mNumColumns);
+        assertEquals("1 key auto 5 R0 rows", 1, params.mNumRows);
+        assertEquals("1 key auto 5 R0 left", 0, params.mLeftKeys);
+        assertEquals("1 key auto 5 R0 right", 1, params.mRightKeys);
+        assertEquals("1 key auto 5 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("1 key auto 5 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key auto 5 R0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // <1> ___|
+    public void testLayout1KeyAuto5R1() {
+        MoreKeysKeyboardParams params = createParams(1, 5, XPOS_R1);
+        assertEquals("1 key auto 5 R1 columns", 1, params.mNumColumns);
+        assertEquals("1 key auto 5 R1 rows", 1, params.mNumRows);
+        assertEquals("1 key auto 5 R1 left", 0, params.mLeftKeys);
+        assertEquals("1 key auto 5 R1 right", 1, params.mRightKeys);
+        assertEquals("1 key auto 5 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("1 key auto 5 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key auto 5 R1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // <1> ___ ___|
+    public void testLayout1KeyAuto5R2() {
+        MoreKeysKeyboardParams params = createParams(1, 5, XPOS_R2);
+        assertEquals("1 key auto 5 R2 columns", 1, params.mNumColumns);
+        assertEquals("1 key auto 5 R2 rows", 1, params.mNumRows);
+        assertEquals("1 key auto 5 R2 left", 0, params.mLeftKeys);
+        assertEquals("1 key auto 5 R2 right", 1, params.mRightKeys);
+        assertEquals("1 key auto 5 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("1 key auto 5 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("1 key auto 5 R2 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // <1> [2]
+    public void testLayout2KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(2, 5, XPOS_M0);
+        assertEquals("2 key auto 5 M0 columns", 2, params.mNumColumns);
+        assertEquals("2 key auto 5 M0 rows", 1, params.mNumRows);
+        assertEquals("2 key auto 5 M0 left", 0, params.mLeftKeys);
+        assertEquals("2 key auto 5 M0 right", 2, params.mRightKeys);
+        assertEquals("2 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("2 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("2 key auto 5 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key auto 5 M0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |<1> [2]
+    public void testLayout2KeyAuto5L0() {
+        MoreKeysKeyboardParams params = createParams(2, 5, XPOS_L0);
+        assertEquals("2 key auto 5 L0 columns", 2, params.mNumColumns);
+        assertEquals("2 key auto 5 L0 rows", 1, params.mNumRows);
+        assertEquals("2 key auto 5 L0 left", 0, params.mLeftKeys);
+        assertEquals("2 key auto 5 L0 right", 2, params.mRightKeys);
+        assertEquals("2 key auto 5 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("2 key auto 5 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("2 key auto 5 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key auto 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ <1> [2]
+    public void testLayout2KeyAuto5L1() {
+        MoreKeysKeyboardParams params = createParams(2, 5, XPOS_L1);
+        assertEquals("2 key auto 5 L1 columns", 2, params.mNumColumns);
+        assertEquals("2 key auto 5 L1 rows", 1, params.mNumRows);
+        assertEquals("2 key auto 5 L1 left", 0, params.mLeftKeys);
+        assertEquals("2 key auto 5 L1 right", 2, params.mRightKeys);
+        assertEquals("2 key auto 5 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("2 key auto 5 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("2 key auto 5 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key auto 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ <1> [2]
+    public void testLayout2KeyAuto5L2() {
+        MoreKeysKeyboardParams params = createParams(2, 5, XPOS_L2);
+        assertEquals("2 key auto 5 L2 columns", 2, params.mNumColumns);
+        assertEquals("2 key auto 5 L2 rows", 1, params.mNumRows);
+        assertEquals("2 key auto 5 L2 left", 0, params.mLeftKeys);
+        assertEquals("2 key auto 5 L2 right", 2, params.mRightKeys);
+        assertEquals("2 key auto 5 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("2 key auto 5 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("2 key auto 5 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key auto 5 L2 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // [2] <1>|
+    public void testLayout2KeyAuto5R0() {
+        MoreKeysKeyboardParams params = createParams(2, 5, XPOS_R0);
+        assertEquals("2 key auto 5 R0 columns", 2, params.mNumColumns);
+        assertEquals("2 key auto 5 R0 rows", 1, params.mNumRows);
+        assertEquals("2 key auto 5 R0 left", 1, params.mLeftKeys);
+        assertEquals("2 key auto 5 R0 right", 1, params.mRightKeys);
+        assertEquals("2 key auto 5 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("2 key auto 5 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("2 key auto 5 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key auto 5 R0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [2] <1> ___|
+    public void testLayout2KeyAuto5R1() {
+        MoreKeysKeyboardParams params = createParams(2, 5, XPOS_R1);
+        assertEquals("2 key auto 5 R1 columns", 2, params.mNumColumns);
+        assertEquals("2 key auto 5 R1 rows", 1, params.mNumRows);
+        assertEquals("2 key auto 5 R1 left", 1, params.mLeftKeys);
+        assertEquals("2 key auto 5 R1 right", 1, params.mRightKeys);
+        assertEquals("2 key auto 5 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("2 key auto 5 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("2 key auto 5 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key auto 5 R1 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // <1> [2] ___|
+    public void testLayout2KeyAuto5R2() {
+        MoreKeysKeyboardParams params = createParams(2, 5, XPOS_R2);
+        assertEquals("2 key auto 5 R2 columns", 2, params.mNumColumns);
+        assertEquals("2 key auto 5 R2 rows", 1, params.mNumRows);
+        assertEquals("2 key auto 5 R2 left", 0, params.mLeftKeys);
+        assertEquals("2 key auto 5 R2 right", 2, params.mRightKeys);
+        assertEquals("2 key auto 5 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("2 key auto 5 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("2 key auto 5 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("2 key auto 5 R2 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // [3] <1> [2]
+    public void testLayout3KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(3, 5, XPOS_M0);
+        assertEquals("3 key auto 5 M0 columns", 3, params.mNumColumns);
+        assertEquals("3 key auto 5 M0 rows", 1, params.mNumRows);
+        assertEquals("3 key auto 5 M0 left", 1, params.mLeftKeys);
+        assertEquals("3 key auto 5 M0 right", 2, params.mRightKeys);
+        assertEquals("3 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("3 key auto 5 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 5 M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |<1> [2] [3]
+    public void testLayout3KeyAuto5L0() {
+        MoreKeysKeyboardParams params = createParams(3, 5, XPOS_L0);
+        assertEquals("3 key auto 5 L0 columns", 3, params.mNumColumns);
+        assertEquals("3 key auto 5 L0 rows", 1, params.mNumRows);
+        assertEquals("3 key auto 5 L0 left", 0, params.mLeftKeys);
+        assertEquals("3 key auto 5 L0 right", 3, params.mRightKeys);
+        assertEquals("3 key auto 5 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 5 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key auto 5 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("3 key auto 5 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ <1> [2] [3]
+    public void testLayout3KeyAuto5L1() {
+        MoreKeysKeyboardParams params = createParams(3, 5, XPOS_L1);
+        assertEquals("3 key auto 5 L1 columns", 3, params.mNumColumns);
+        assertEquals("3 key auto 5 L1 rows", 1, params.mNumRows);
+        assertEquals("3 key auto 5 L1 left", 0, params.mLeftKeys);
+        assertEquals("3 key auto 5 L1 right", 3, params.mRightKeys);
+        assertEquals("3 key auto 5 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 5 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key auto 5 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("3 key auto 5 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [3] <1> [2]
+    public void testLayout3KeyAuto5L2() {
+        MoreKeysKeyboardParams params = createParams(3, 5, XPOS_L2);
+        assertEquals("3 key auto 5 L2 columns", 3, params.mNumColumns);
+        assertEquals("3 key auto 5 L2 rows", 1, params.mNumRows);
+        assertEquals("3 key auto 5 L2 left", 1, params.mLeftKeys);
+        assertEquals("3 key auto 5 L2 right", 2, params.mRightKeys);
+        assertEquals("3 key auto 5 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 5 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key auto 5 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("3 key auto 5 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [3] [2] <1>|
+    public void testLayout3KeyAuto5R0() {
+        MoreKeysKeyboardParams params = createParams(3, 5, XPOS_R0);
+        assertEquals("3 key auto 5 R0 columns", 3, params.mNumColumns);
+        assertEquals("3 key auto 5 R0 rows", 1, params.mNumRows);
+        assertEquals("3 key auto 5 R0 left", 2, params.mLeftKeys);
+        assertEquals("3 key auto 5 R0 right", 1, params.mRightKeys);
+        assertEquals("3 key auto 5 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 5 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("3 key auto 5 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("3 key auto 5 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 5 R0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // [3] [2] <1> ___|
+    public void testLayout3KeyAuto5R1() {
+        MoreKeysKeyboardParams params = createParams(3, 5, XPOS_R1);
+        assertEquals("3 key auto 5 R1 columns", 3, params.mNumColumns);
+        assertEquals("3 key auto 5 R1 rows", 1, params.mNumRows);
+        assertEquals("3 key auto 5 R1 left", 2, params.mLeftKeys);
+        assertEquals("3 key auto 5 R1 right", 1, params.mRightKeys);
+        assertEquals("3 key auto 5 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 5 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("3 key auto 5 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("3 key auto 5 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 5 R1 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // [3] <1> [2] ___|
+    public void testLayout3KeyAuto5R2() {
+        MoreKeysKeyboardParams params = createParams(3, 5, XPOS_R2);
+        assertEquals("3 key auto 5 R2 columns", 3, params.mNumColumns);
+        assertEquals("3 key auto 5 R2 rows", 1, params.mNumRows);
+        assertEquals("3 key auto 5 R2 left", 1, params.mLeftKeys);
+        assertEquals("3 key auto 5 R2 right", 2, params.mRightKeys);
+        assertEquals("3 key auto 5 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 5 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key auto 5 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("3 key auto 5 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 5 R2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [3]
+    // <1> [2]
+    public void testLayout3KeyAuto2M0() {
+        MoreKeysKeyboardParams params = createParams(3, 2, XPOS_M0);
+        assertEquals("3 key auto 2 M0 columns", 2, params.mNumColumns);
+        assertEquals("3 key auto 2 M0 rows", 2, params.mNumRows);
+        assertEquals("3 key auto 2 M0 left", 0, params.mLeftKeys);
+        assertEquals("3 key auto 2 M0 right", 2, params.mRightKeys);
+        assertEquals("3 key auto 2 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 2 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key auto 2 M0 [3]", 0, params.getColumnPos(2));
+        assertEquals("3 key auto 2 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 2 M0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |[3]
+    // |<1> [2]
+    public void testLayout3KeyAuto2L0() {
+        MoreKeysKeyboardParams params = createParams(3, 2, XPOS_L0);
+        assertEquals("3 key auto 2 L0 columns", 2, params.mNumColumns);
+        assertEquals("3 key auto 2 L0 rows", 2, params.mNumRows);
+        assertEquals("3 key auto 2 L0 left", 0, params.mLeftKeys);
+        assertEquals("3 key auto 2 L0 right", 2, params.mRightKeys);
+        assertEquals("3 key auto 2 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 2 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key auto 2 L0 [3]", 0, params.getColumnPos(2));
+        assertEquals("3 key auto 2 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 2 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [3]
+    // |___ <1> [2]
+    public void testLayout3KeyAuto2L1() {
+        MoreKeysKeyboardParams params = createParams(3, 2, XPOS_L1);
+        assertEquals("3 key auto 2 L1 columns", 2, params.mNumColumns);
+        assertEquals("3 key auto 2 L1 rows", 2, params.mNumRows);
+        assertEquals("3 key auto 2 L1 left", 0, params.mLeftKeys);
+        assertEquals("3 key auto 2 L1 right", 2, params.mRightKeys);
+        assertEquals("3 key auto 2 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 2 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key auto 2 L1 [3]", 0, params.getColumnPos(2));
+        assertEquals("3 key auto 2 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 2 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |        [3]
+    // |___ ___ <1> [2]
+    public void testLayout3KeyAuto2L2() {
+        MoreKeysKeyboardParams params = createParams(3, 2, XPOS_L2);
+        assertEquals("3 key auto 2 L2 columns", 2, params.mNumColumns);
+        assertEquals("3 key auto 2 L2 rows", 2, params.mNumRows);
+        assertEquals("3 key auto 2 L2 left", 0, params.mLeftKeys);
+        assertEquals("3 key auto 2 L2 right", 2, params.mRightKeys);
+        assertEquals("3 key auto 2 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 2 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key auto 2 L2 [3]", 0, params.getColumnPos(2));
+        assertEquals("3 key auto 2 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 2 L2 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    //     [3]|
+    // [2] <1>|
+    public void testLayout3KeyAuto2R0() {
+        MoreKeysKeyboardParams params = createParams(3, 2, XPOS_R0);
+        assertEquals("3 key auto 2 R0 columns", 2, params.mNumColumns);
+        assertEquals("3 key auto 2 R0 rows", 2, params.mNumRows);
+        assertEquals("3 key auto 2 R0 left", 1, params.mLeftKeys);
+        assertEquals("3 key auto 2 R0 right", 1, params.mRightKeys);
+        assertEquals("3 key auto 2 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 2 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("3 key auto 2 R0 [3]", 0, params.getColumnPos(2));
+        assertEquals("3 key auto 2 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 2 R0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //     [3]    |
+    // [2] <1> ___|
+    public void testLayout3KeyAuto2R1() {
+        MoreKeysKeyboardParams params = createParams(3, 2, XPOS_R1);
+        assertEquals("3 key auto 2 R1 columns", 2, params.mNumColumns);
+        assertEquals("3 key auto 2 R1 rows", 2, params.mNumRows);
+        assertEquals("3 key auto 2 R1 left", 1, params.mLeftKeys);
+        assertEquals("3 key auto 2 R1 right", 1, params.mRightKeys);
+        assertEquals("3 key auto 2 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 2 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("3 key auto 2 R1 [3]", 0, params.getColumnPos(2));
+        assertEquals("3 key auto 2 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 2 R1 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [3]        |
+    // <1> [2] ___|
+    public void testLayout3KeyAuto2R2() {
+        MoreKeysKeyboardParams params = createParams(3, 2, XPOS_R2);
+        assertEquals("3 key auto 2 R2 columns", 2, params.mNumColumns);
+        assertEquals("3 key auto 2 R2 rows", 2, params.mNumRows);
+        assertEquals("3 key auto 2 R2 left", 0, params.mLeftKeys);
+        assertEquals("3 key auto 2 R2 right", 2, params.mRightKeys);
+        assertEquals("3 key auto 2 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("3 key auto 2 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("3 key auto 2 R2 [3]", 0, params.getColumnPos(2));
+        assertEquals("3 key auto 2 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("3 key auto 2 R2 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    //     [4]
+    // [3] <1> [2]
+    public void testLayout4KeyAuto3M0() {
+        MoreKeysKeyboardParams params = createParams(4, 3, XPOS_M0);
+        assertEquals("4 key auto 3 M0 columns", 3, params.mNumColumns);
+        assertEquals("4 key auto 3 M0 rows", 2, params.mNumRows);
+        assertEquals("4 key auto 3 M0 left", 1, params.mLeftKeys);
+        assertEquals("4 key auto 3 M0 right", 2, params.mRightKeys);
+        assertEquals("4 key auto 3 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 3 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 3 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key auto 3 M0 [4]", 0, params.getColumnPos(3));
+        assertEquals("4 key auto 3 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 3 M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |[4]
+    // |<1> [2] [3]
+    public void testLayout4KeyAuto3L0() {
+        MoreKeysKeyboardParams params = createParams(4, 3, XPOS_L0);
+        assertEquals("4 key auto 3 L0 columns", 3, params.mNumColumns);
+        assertEquals("4 key auto 3 L0 rows", 2, params.mNumRows);
+        assertEquals("4 key auto 3 L0 left", 0, params.mLeftKeys);
+        assertEquals("4 key auto 3 L0 right", 3, params.mRightKeys);
+        assertEquals("4 key auto 3 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 3 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 3 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("4 key auto 3 L0 [4]", 0, params.getColumnPos(3));
+        assertEquals("4 key auto 3 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 3 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [4]
+    // |___ <1> [2] [3]
+    public void testLayout4KeyAuto3L1() {
+        MoreKeysKeyboardParams params = createParams(4, 3, XPOS_L1);
+        assertEquals("4 key auto 3 L1 columns", 3, params.mNumColumns);
+        assertEquals("4 key auto 3 L1 rows", 2, params.mNumRows);
+        assertEquals("4 key auto 3 L1 left", 0, params.mLeftKeys);
+        assertEquals("4 key auto 3 L1 right", 3, params.mRightKeys);
+        assertEquals("4 key auto 3 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 3 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 3 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("4 key auto 3 L1 [4]", 0, params.getColumnPos(3));
+        assertEquals("4 key auto 3 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 3 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [4]
+    // |___ [3] <1> [2]
+    public void testLayout4KeyAuto3L2() {
+        MoreKeysKeyboardParams params = createParams(4, 3, XPOS_L2);
+        assertEquals("4 key auto 3 L2 columns", 3, params.mNumColumns);
+        assertEquals("4 key auto 3 L2 rows", 2, params.mNumRows);
+        assertEquals("4 key auto 3 L2 left", 1, params.mLeftKeys);
+        assertEquals("4 key auto 3 L2 right", 2, params.mRightKeys);
+        assertEquals("4 key auto 3 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 3 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 3 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key auto 3 L2 [4]", 0, params.getColumnPos(3));
+        assertEquals("4 key auto 3 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 3 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //         [4]|
+    // [3] [2] <1>|
+    public void testLayout4KeyAuto3R0() {
+        MoreKeysKeyboardParams params = createParams(4, 3, XPOS_R0);
+        assertEquals("4 key auto 3 R0 columns", 3, params.mNumColumns);
+        assertEquals("4 key auto 3 R0 rows", 2, params.mNumRows);
+        assertEquals("4 key auto 3 R0 left", 2, params.mLeftKeys);
+        assertEquals("4 key auto 3 R0 right", 1, params.mRightKeys);
+        assertEquals("4 key auto 3 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 3 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("4 key auto 3 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("4 key auto 3 R0 [4]", 0, params.getColumnPos(3));
+        assertEquals("4 key auto 3 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 3 R0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //         [4] ___|
+    // [3] [2] <1> ___|
+    public void testLayout4KeyAuto3R1() {
+        MoreKeysKeyboardParams params = createParams(4, 3, XPOS_R1);
+        assertEquals("4 key auto 3 R1 columns", 3, params.mNumColumns);
+        assertEquals("4 key auto 3 R1 rows", 2, params.mNumRows);
+        assertEquals("4 key auto 3 R1 left", 2, params.mLeftKeys);
+        assertEquals("4 key auto 3 R1 right", 1, params.mRightKeys);
+        assertEquals("4 key auto 3 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 3 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("4 key auto 3 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("4 key auto 3 R1 [4]", 0, params.getColumnPos(3));
+        assertEquals("4 key auto 3 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 3 R1 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //     [4]     ___|
+    // [3] <1> [2] ___|
+    public void testLayout4KeyAuto3R2() {
+        MoreKeysKeyboardParams params = createParams(4, 3, XPOS_R2);
+        assertEquals("4 key auto 3 R2 columns", 3, params.mNumColumns);
+        assertEquals("4 key auto 3 R2 rows", 2, params.mNumRows);
+        assertEquals("4 key auto 3 R2 left", 1, params.mLeftKeys);
+        assertEquals("4 key auto 3 R2 right", 2, params.mRightKeys);
+        assertEquals("4 key auto 3 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 3 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 3 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key auto 3 R2 [4]", 0, params.getColumnPos(3));
+        assertEquals("4 key auto 3 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 3 R2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [3] <1> [2] [4]
+    public void testLayout4KeyAuto4M0() {
+        MoreKeysKeyboardParams params = createParams(4, 4, XPOS_M0);
+        assertEquals("4 key auto 4 M0 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 4 M0 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 4 M0 left", 1, params.mLeftKeys);
+        assertEquals("4 key auto 4 M0 right", 3, params.mRightKeys);
+        assertEquals("4 key auto 4 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 4 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 4 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key auto 4 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("4 key auto 4 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 4 M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |<1> [2] [3] [4]
+    public void testLayout4KeyAuto4L0() {
+        MoreKeysKeyboardParams params = createParams(4, 4, XPOS_L0);
+        assertEquals("4 key auto 4 L0 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 4 L0 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 4 L0 left", 0, params.mLeftKeys);
+        assertEquals("4 key auto 4 L0 right", 4, params.mRightKeys);
+        assertEquals("4 key auto 4 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 4 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 4 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("4 key auto 4 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("4 key auto 4 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 4 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ <1> [2] [3] [4]
+    public void testLayout4KeyAuto4L1() {
+        MoreKeysKeyboardParams params = createParams(4, 4, XPOS_L1);
+        assertEquals("4 key auto 4 L1 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 4 L1 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 4 L1 left", 0, params.mLeftKeys);
+        assertEquals("4 key auto 4 L1 right", 4, params.mRightKeys);
+        assertEquals("4 key auto 4 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 4 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 4 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("4 key auto 4 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("4 key auto 4 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 4 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [3] <1> [2] [4]
+    public void testLayout4KeyAuto4L2() {
+        MoreKeysKeyboardParams params = createParams(4, 4, XPOS_L2);
+        assertEquals("4 key auto 4 L2 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 4 L2 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 4 L2 left", 1, params.mLeftKeys);
+        assertEquals("4 key auto 4 L2 right", 3, params.mRightKeys);
+        assertEquals("4 key auto 4 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 4 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 4 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key auto 4 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("4 key auto 4 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 4 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [4] [3] [2] <1>|
+    public void testLayout4KeyAuto4R0() {
+        MoreKeysKeyboardParams params = createParams(4, 4, XPOS_R0);
+        assertEquals("4 key auto 4 R0 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 4 R0 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 4 R0 left", 3, params.mLeftKeys);
+        assertEquals("4 key auto 4 R0 right", 1, params.mRightKeys);
+        assertEquals("4 key auto 4 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 4 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("4 key auto 4 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("4 key auto 4 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("4 key auto 4 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 4 R0 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [4] [3] [2] <1> ___|
+    public void testLayout4KeyAuto4R1() {
+        MoreKeysKeyboardParams params = createParams(4, 4, XPOS_R1);
+        assertEquals("4 key auto 4 R1 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 4 R1 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 4 R1 left", 3, params.mLeftKeys);
+        assertEquals("4 key auto 4 R1 right", 1, params.mRightKeys);
+        assertEquals("4 key auto 4 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 4 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("4 key auto 4 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("4 key auto 4 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("4 key auto 4 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 4 R1 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [4] [3] <1> [2] ___|
+    public void testLayout4KeyAuto4R2() {
+        MoreKeysKeyboardParams params = createParams(4, 4, XPOS_R2);
+        assertEquals("4 key auto 4 R2 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 4 R2 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 4 R2 left", 2, params.mLeftKeys);
+        assertEquals("4 key auto 4 R2 right", 2, params.mRightKeys);
+        assertEquals("4 key auto 4 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 4 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 4 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key auto 4 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("4 key auto 4 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 4 R2 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // [3] <1> [2] [4]
+    public void testLayout4KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(4, 5, XPOS_M0);
+        assertEquals("4 key auto 5 M0 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 5 M0 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 5 M0 left", 1, params.mLeftKeys);
+        assertEquals("4 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("4 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("4 key auto 5 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 5 M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |<1> [2] [3] [4]
+    public void testLayout4KeyAuto5L0() {
+        MoreKeysKeyboardParams params = createParams(4, 5, XPOS_L0);
+        assertEquals("4 key auto 5 L0 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 5 L0 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 5 L0 left", 0, params.mLeftKeys);
+        assertEquals("4 key auto 5 L0 right", 4, params.mRightKeys);
+        assertEquals("4 key auto 5 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 5 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 5 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("4 key auto 5 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("4 key auto 5 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ <1> [2] [3] [4]
+    public void testLayout4KeyAuto5L1() {
+        MoreKeysKeyboardParams params = createParams(4, 5, XPOS_L1);
+        assertEquals("4 key auto 5 L1 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 5 L1 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 5 L1 left", 0, params.mLeftKeys);
+        assertEquals("4 key auto 5 L1 right", 4, params.mRightKeys);
+        assertEquals("4 key auto 5 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 5 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 5 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("4 key auto 5 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("4 key auto 5 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [3] <1> [2] [4]
+    public void testLayout4KeyAuto5L2() {
+        MoreKeysKeyboardParams params = createParams(4, 5, XPOS_L2);
+        assertEquals("4 key auto 5 L2 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 5 L2 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 5 L2 left", 1, params.mLeftKeys);
+        assertEquals("4 key auto 5 L2 right", 3, params.mRightKeys);
+        assertEquals("4 key auto 5 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 5 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 5 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key auto 5 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("4 key auto 5 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [4] [3] [2] <1>|
+    public void testLayout4KeyAuto5R0() {
+        MoreKeysKeyboardParams params = createParams(4, 5, XPOS_R0);
+        assertEquals("4 key auto 5 R0 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 5 R0 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 5 R0 left", 3, params.mLeftKeys);
+        assertEquals("4 key auto 5 R0 right", 1, params.mRightKeys);
+        assertEquals("4 key auto 5 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 5 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("4 key auto 5 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("4 key auto 5 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("4 key auto 5 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 5 R0 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [4] [3] [2] <1> ___|
+    public void testLayout4KeyAuto5R1() {
+        MoreKeysKeyboardParams params = createParams(4, 5, XPOS_R1);
+        assertEquals("4 key auto 5 R1 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 5 R1 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 5 R1 left", 3, params.mLeftKeys);
+        assertEquals("4 key auto 5 R1 right", 1, params.mRightKeys);
+        assertEquals("4 key auto 5 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 5 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("4 key auto 5 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("4 key auto 5 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("4 key auto 5 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 5 R1 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [4] [3] <1> [2] ___|
+    public void testLayout4KeyAuto5R2() {
+        MoreKeysKeyboardParams params = createParams(4, 5, XPOS_R2);
+        assertEquals("4 key auto 5 R2 columns", 4, params.mNumColumns);
+        assertEquals("4 key auto 5 R2 rows", 1, params.mNumRows);
+        assertEquals("4 key auto 5 R2 left", 2, params.mLeftKeys);
+        assertEquals("4 key auto 5 R2 right", 2, params.mRightKeys);
+        assertEquals("4 key auto 5 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("4 key auto 5 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("4 key auto 5 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("4 key auto 5 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("4 key auto 5 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("4 key auto 5 R2 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //   [4] [5]
+    // [3] <1> [2]
+    public void testLayout5KeyAuto3M0() {
+        MoreKeysKeyboardParams params = createParams(5, 3, XPOS_M0);
+        assertEquals("5 key auto 3 M0 columns", 3, params.mNumColumns);
+        assertEquals("5 key auto 3 M0 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 3 M0 left", 1, params.mLeftKeys);
+        assertEquals("5 key auto 3 M0 right", 2, params.mRightKeys);
+        assertEquals("5 key auto 3 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 3 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 3 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key auto 3 M0 [4]", 0, params.getColumnPos(3));
+        assertEquals("5 key auto 3 M0 [5]", 1, params.getColumnPos(4));
+        assertEquals("5 key auto 3 M0 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("5 key auto 3 M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |[4] [5]
+    // |<1> [2] [3]
+    public void testLayout5KeyAuto3L0() {
+        MoreKeysKeyboardParams params = createParams(5, 3, XPOS_L0);
+        assertEquals("5 key auto 3 L0 columns", 3, params.mNumColumns);
+        assertEquals("5 key auto 3 L0 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 3 L0 left", 0, params.mLeftKeys);
+        assertEquals("5 key auto 3 L0 right", 3, params.mRightKeys);
+        assertEquals("5 key auto 3 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 3 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 3 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("5 key auto 3 L0 [4]", 0, params.getColumnPos(3));
+        assertEquals("5 key auto 3 L0 [5]", 1, params.getColumnPos(4));
+        assertEquals("5 key auto 3 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 3 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [4] [5]
+    // |___ <1> [2] [3]
+    public void testLayout5KeyAuto3L1() {
+        MoreKeysKeyboardParams params = createParams(5, 3, XPOS_L1);
+        assertEquals("5 key auto 3 L1 columns", 3, params.mNumColumns);
+        assertEquals("5 key auto 3 L1 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 3 L1 left", 0, params.mLeftKeys);
+        assertEquals("5 key auto 3 L1 right", 3, params.mRightKeys);
+        assertEquals("5 key auto 3 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 3 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 3 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("5 key auto 3 L1 [4]", 0, params.getColumnPos(3));
+        assertEquals("5 key auto 3 L1 [5]", 1, params.getColumnPos(4));
+        assertEquals("5 key auto 3 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 3 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___   [4] [5]
+    // |___ [3] <1> [2]
+    public void testLayout5KeyAuto3L2() {
+        MoreKeysKeyboardParams params = createParams(5, 3, XPOS_L2);
+        assertEquals("5 key auto 3 L2 columns", 3, params.mNumColumns);
+        assertEquals("5 key auto 3 L2 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 3 L2 left", 1, params.mLeftKeys);
+        assertEquals("5 key auto 3 L2 right", 2, params.mRightKeys);
+        assertEquals("5 key auto 3 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 3 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 3 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key auto 3 L2 [4]", 0, params.getColumnPos(3));
+        assertEquals("5 key auto 3 L2 [5]", 1, params.getColumnPos(4));
+        assertEquals("5 key auto 3 L2 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("5 key auto 3 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //     [5] [4]|
+    // [3] [2] <1>|
+    public void testLayout5KeyAuto3R0() {
+        MoreKeysKeyboardParams params = createParams(5, 3, XPOS_R0);
+        assertEquals("5 key auto 3 R0 columns", 3, params.mNumColumns);
+        assertEquals("5 key auto 3 R0 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 3 R0 left", 2, params.mLeftKeys);
+        assertEquals("5 key auto 3 R0 right", 1, params.mRightKeys);
+        assertEquals("5 key auto 3 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 3 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("5 key auto 3 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("5 key auto 3 R0 [4]", 0, params.getColumnPos(3));
+        assertEquals("5 key auto 3 R0 [5]", -1, params.getColumnPos(4));
+        assertEquals("5 key auto 3 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 3 R0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //     [5] [4] ___|
+    // [3] [2] <1> ___|
+    public void testLayout5KeyAuto3R1() {
+        MoreKeysKeyboardParams params = createParams(5, 3, XPOS_R1);
+        assertEquals("5 key auto 3 R1 columns", 3, params.mNumColumns);
+        assertEquals("5 key auto 3 R1 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 3 R1 left", 2, params.mLeftKeys);
+        assertEquals("5 key auto 3 R1 right", 1, params.mRightKeys);
+        assertEquals("5 key auto 3 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 3 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("5 key auto 3 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("5 key auto 3 R1 [4]", 0, params.getColumnPos(3));
+        assertEquals("5 key auto 3 R1 [5]", -1, params.getColumnPos(4));
+        assertEquals("5 key auto 3 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 3 R1 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //   [4] [5]   ___|
+    // [3] <1> [2] ___|
+    public void testLayout5KeyAuto3R2() {
+        MoreKeysKeyboardParams params = createParams(5, 3, XPOS_R2);
+        assertEquals("5 key auto 3 R2 columns", 3, params.mNumColumns);
+        assertEquals("5 key auto 3 R2 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 3 R2 left", 1, params.mLeftKeys);
+        assertEquals("5 key auto 3 R2 right", 2, params.mRightKeys);
+        assertEquals("5 key auto 3 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 3 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 3 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key auto 3 R2 [4]", 0, params.getColumnPos(3));
+        assertEquals("5 key auto 3 R2 [5]", 1, params.getColumnPos(4));
+        assertEquals("5 key auto 3 R2 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("5 key auto 3 R2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //     [5]
+    // [3] <1> [2] [4]
+    public void testLayout5KeyAuto4M0() {
+        MoreKeysKeyboardParams params = createParams(5, 4, XPOS_M0);
+        assertEquals("5 key auto 4 M0 columns", 4, params.mNumColumns);
+        assertEquals("5 key auto 4 M0 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 4 M0 left", 1, params.mLeftKeys);
+        assertEquals("5 key auto 4 M0 right", 3, params.mRightKeys);
+        assertEquals("5 key auto 4 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 4 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 4 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key auto 4 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("5 key auto 4 M0 [5]", 0, params.getColumnPos(4));
+        assertEquals("5 key auto 4 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 4 M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |[5]
+    // |<1> [2] [3] [4]
+    public void testLayout5KeyAuto4L0() {
+        MoreKeysKeyboardParams params = createParams(5, 4, XPOS_L0);
+        assertEquals("5 key auto 4 L0 columns", 4, params.mNumColumns);
+        assertEquals("5 key auto 4 L0 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 4 L0 left", 0, params.mLeftKeys);
+        assertEquals("5 key auto 4 L0 right", 4, params.mRightKeys);
+        assertEquals("5 key auto 4 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 4 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 4 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("5 key auto 4 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("5 key auto 4 L0 [5]", 0, params.getColumnPos(4));
+        assertEquals("5 key auto 4 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 4 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [5]
+    // |___ <1> [2] [3] [4]
+    public void testLayout5KeyAuto4L1() {
+        MoreKeysKeyboardParams params = createParams(5, 4, XPOS_L1);
+        assertEquals("5 key auto 4 L1 columns", 4, params.mNumColumns);
+        assertEquals("5 key auto 4 L1 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 4 L1 left", 0, params.mLeftKeys);
+        assertEquals("5 key auto 4 L1 right", 4, params.mRightKeys);
+        assertEquals("5 key auto 4 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 4 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 4 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("5 key auto 4 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("5 key auto 4 L1 [5]", 0, params.getColumnPos(4));
+        assertEquals("5 key auto 4 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 4 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___     [5]
+    // |___ [3] <1> [2] [4]
+    public void testLayout5KeyAuto4L2() {
+        MoreKeysKeyboardParams params = createParams(5, 4, XPOS_L2);
+        assertEquals("5 key auto 4 L2 columns", 4, params.mNumColumns);
+        assertEquals("5 key auto 4 L2 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 4 L2 left", 1, params.mLeftKeys);
+        assertEquals("5 key auto 4 L2 right", 3, params.mRightKeys);
+        assertEquals("5 key auto 4 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 4 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 4 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key auto 4 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("5 key auto 4 L2 [5]", 0, params.getColumnPos(4));
+        assertEquals("5 key auto 4 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 4 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //             [5]|
+    // [4] [3] [2] <1>|
+    public void testLayout5KeyAuto4R0() {
+        MoreKeysKeyboardParams params = createParams(5, 4, XPOS_R0);
+        assertEquals("5 key auto 4 R0 columns", 4, params.mNumColumns);
+        assertEquals("5 key auto 4 R0 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 4 R0 left", 3, params.mLeftKeys);
+        assertEquals("5 key auto 4 R0 right", 1, params.mRightKeys);
+        assertEquals("5 key auto 4 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 4 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("5 key auto 4 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("5 key auto 4 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("5 key auto 4 R0 [5]", 0, params.getColumnPos(4));
+        assertEquals("5 key auto 4 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 4 R0 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //             [5] ___|
+    // [4] [3] [2] <1> ___|
+    public void testLayout5KeyAuto4R1() {
+        MoreKeysKeyboardParams params = createParams(5, 4, XPOS_R1);
+        assertEquals("5 key auto 4 R1 columns", 4, params.mNumColumns);
+        assertEquals("5 key auto 4 R1 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 4 R1 left", 3, params.mLeftKeys);
+        assertEquals("5 key auto 4 R1 right", 1, params.mRightKeys);
+        assertEquals("5 key auto 4 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 4 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("5 key auto 4 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("5 key auto 4 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("5 key auto 4 R1 [5]", 0, params.getColumnPos(4));
+        assertEquals("5 key auto 4 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 4 R1 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //         [5]     ___|
+    // [4] [3] <1> [2] ___|
+    public void testLayout5KeyAuto4R2() {
+        MoreKeysKeyboardParams params = createParams(5, 4, XPOS_R2);
+        assertEquals("5 key auto 4 R2 columns", 4, params.mNumColumns);
+        assertEquals("5 key auto 4 R2 rows", 2, params.mNumRows);
+        assertEquals("5 key auto 4 R2 left", 2, params.mLeftKeys);
+        assertEquals("5 key auto 4 R2 right", 2, params.mRightKeys);
+        assertEquals("5 key auto 4 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 4 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 4 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key auto 4 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("5 key auto 4 R2 [5]", 0, params.getColumnPos(4));
+        assertEquals("5 key auto 4 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 4 R2 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // [5] [3] <1> [2] [4]
+    public void testLayout5KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(5, 5, XPOS_M0);
+        assertEquals("5 key auto 5 M0 columns", 5, params.mNumColumns);
+        assertEquals("5 key auto 5 M0 rows", 1, params.mNumRows);
+        assertEquals("5 key auto 5 M0 left", 2, params.mLeftKeys);
+        assertEquals("5 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("5 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("5 key auto 5 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("5 key auto 5 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // |<1> [2] [3] [4] [5]
+    public void testLayout5KeyAuto5L0() {
+        MoreKeysKeyboardParams params = createParams(5, 5, XPOS_L0);
+        assertEquals("5 key auto 5 L0 columns", 5, params.mNumColumns);
+        assertEquals("5 key auto 5 L0 rows", 1, params.mNumRows);
+        assertEquals("5 key auto 5 L0 left", 0, params.mLeftKeys);
+        assertEquals("5 key auto 5 L0 right", 5, params.mRightKeys);
+        assertEquals("5 key auto 5 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 5 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 5 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("5 key auto 5 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("5 key auto 5 L0 [5]", 4, params.getColumnPos(4));
+        assertEquals("5 key auto 5 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ <1> [2] [3] [4] [5]
+    public void testLayout5KeyAuto5L1() {
+        MoreKeysKeyboardParams params = createParams(5, 5, XPOS_L1);
+        assertEquals("5 key auto 5 L1 columns", 5, params.mNumColumns);
+        assertEquals("5 key auto 5 L1 rows", 1, params.mNumRows);
+        assertEquals("5 key auto 5 L1 left", 0, params.mLeftKeys);
+        assertEquals("5 key auto 5 L1 right", 5, params.mRightKeys);
+        assertEquals("5 key auto 5 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 5 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 5 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("5 key auto 5 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("5 key auto 5 L1 [5]", 4, params.getColumnPos(4));
+        assertEquals("5 key auto 5 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [3] <1> [2] [4] [5]
+    public void testLayout5KeyAuto5L2() {
+        MoreKeysKeyboardParams params = createParams(5, 5, XPOS_L2);
+        assertEquals("5 key auto 5 L2 columns", 5, params.mNumColumns);
+        assertEquals("5 key auto 5 L2 rows", 1, params.mNumRows);
+        assertEquals("5 key auto 5 L2 left", 1, params.mLeftKeys);
+        assertEquals("5 key auto 5 L2 right", 4, params.mRightKeys);
+        assertEquals("5 key auto 5 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 5 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 5 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key auto 5 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("5 key auto 5 L2 [5]", 3, params.getColumnPos(4));
+        assertEquals("5 key auto 5 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [5] [4] [3] [2] <1>|
+    public void testLayout5KeyAuto5R0() {
+        MoreKeysKeyboardParams params = createParams(5, 5, XPOS_R0);
+        assertEquals("5 key auto 5 R0 columns", 5, params.mNumColumns);
+        assertEquals("5 key auto 5 R0 rows", 1, params.mNumRows);
+        assertEquals("5 key auto 5 R0 left", 4, params.mLeftKeys);
+        assertEquals("5 key auto 5 R0 right", 1, params.mRightKeys);
+        assertEquals("5 key auto 5 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 5 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("5 key auto 5 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("5 key auto 5 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("5 key auto 5 R0 [5]", -4, params.getColumnPos(4));
+        assertEquals("5 key auto 5 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    // [5] [4] [3] [2] <1> ___|
+    public void testLayout5KeyAuto5R1() {
+        MoreKeysKeyboardParams params = createParams(5, 5, XPOS_R1);
+        assertEquals("5 key auto 5 R1 columns", 5, params.mNumColumns);
+        assertEquals("5 key auto 5 R1 rows", 1, params.mNumRows);
+        assertEquals("5 key auto 5 R1 left", 4, params.mLeftKeys);
+        assertEquals("5 key auto 5 R1 right", 1, params.mRightKeys);
+        assertEquals("5 key auto 5 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 5 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("5 key auto 5 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("5 key auto 5 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("5 key auto 5 R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("5 key auto 5 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    // [5] [4] [3] <1> [2] ___|
+    public void testLayout5KeyAuto5R2() {
+        MoreKeysKeyboardParams params = createParams(5, 5, XPOS_R2);
+        assertEquals("5 key auto 5 R2 columns", 5, params.mNumColumns);
+        assertEquals("5 key auto 5 R2 rows", 1, params.mNumRows);
+        assertEquals("5 key auto 5 R2 left", 3, params.mLeftKeys);
+        assertEquals("5 key auto 5 R2 right", 2, params.mRightKeys);
+        assertEquals("5 key auto 5 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("5 key auto 5 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("5 key auto 5 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("5 key auto 5 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("5 key auto 5 R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("5 key auto 5 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("5 key auto 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //     [5] [6]
+    // [3] <1> [2] [4]
+    public void testLayout6KeyAuto4M0() {
+        MoreKeysKeyboardParams params = createParams(6, 4, XPOS_M0);
+        assertEquals("6 key auto 4 M0 columns", 4, params.mNumColumns);
+        assertEquals("6 key auto 4 M0 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 4 M0 left", 1, params.mLeftKeys);
+        assertEquals("6 key auto 4 M0 right", 3, params.mRightKeys);
+        assertEquals("6 key auto 4 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 4 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key auto 4 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("6 key auto 4 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("6 key auto 4 M0 [5]", 0, params.getColumnPos(4));
+        assertEquals("6 key auto 4 M0 [6]", 1, params.getColumnPos(5));
+        assertEquals("6 key auto 4 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 4 M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |[5] [6]
+    // |<1> [2] [3] [4]
+    public void testLayout6KeyAuto4L0() {
+        MoreKeysKeyboardParams params = createParams(6, 4, XPOS_L0);
+        assertEquals("6 key auto 4 L0 columns", 4, params.mNumColumns);
+        assertEquals("6 key auto 4 L0 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 4 L0 left", 0, params.mLeftKeys);
+        assertEquals("6 key auto 4 L0 right", 4, params.mRightKeys);
+        assertEquals("6 key auto 4 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 4 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key auto 4 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("6 key auto 4 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("6 key auto 4 L0 [5]", 0, params.getColumnPos(4));
+        assertEquals("6 key auto 4 L0 [6]", 1, params.getColumnPos(5));
+        assertEquals("6 key auto 4 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 4 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [5] [6]
+    // |___ <1> [2] [3] [4]
+    public void testLayout6KeyAuto4L1() {
+        MoreKeysKeyboardParams params = createParams(6, 4, XPOS_L1);
+        assertEquals("6 key auto 4 L1 columns", 4, params.mNumColumns);
+        assertEquals("6 key auto 4 L1 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 4 L1 left", 0, params.mLeftKeys);
+        assertEquals("6 key auto 4 L1 right", 4, params.mRightKeys);
+        assertEquals("6 key auto 4 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 4 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key auto 4 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("6 key auto 4 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("6 key auto 4 L1 [5]", 0, params.getColumnPos(4));
+        assertEquals("6 key auto 4 L1 [6]", 1, params.getColumnPos(5));
+        assertEquals("6 key auto 4 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 4 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___     [5] [6]
+    // |___ [3] <1> [2] [4]
+    public void testLayout6KeyAuto4L2() {
+        MoreKeysKeyboardParams params = createParams(6, 4, XPOS_L2);
+        assertEquals("6 key auto 4 L2 columns", 4, params.mNumColumns);
+        assertEquals("6 key auto 4 L2 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 4 L2 left", 1, params.mLeftKeys);
+        assertEquals("6 key auto 4 L2 right", 3, params.mRightKeys);
+        assertEquals("6 key auto 4 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 4 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key auto 4 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("6 key auto 4 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("6 key auto 4 L2 [5]", 0, params.getColumnPos(4));
+        assertEquals("6 key auto 4 L2 [6]", 1, params.getColumnPos(5));
+        assertEquals("6 key auto 4 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 4 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //         [6] [5]|
+    // [4] [3] [2] <1>|
+    public void testLayout6KeyAuto4R0() {
+        MoreKeysKeyboardParams params = createParams(6, 4, XPOS_R0);
+        assertEquals("6 key auto 4 R0 columns", 4, params.mNumColumns);
+        assertEquals("6 key auto 4 R0 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 4 R0 left", 3, params.mLeftKeys);
+        assertEquals("6 key auto 4 R0 right", 1, params.mRightKeys);
+        assertEquals("6 key auto 4 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 4 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("6 key auto 4 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("6 key auto 4 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("6 key auto 4 R0 [5]", 0, params.getColumnPos(4));
+        assertEquals("6 key auto 4 R0 [6]", -1, params.getColumnPos(5));
+        assertEquals("6 key auto 4 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 4 R0 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //         [6] [5] ___|
+    // [4] [3] [2] <1> ___|
+    public void testLayout6KeyAuto4R1() {
+        MoreKeysKeyboardParams params = createParams(6, 4, XPOS_R1);
+        assertEquals("6 key auto 4 R1 columns", 4, params.mNumColumns);
+        assertEquals("6 key auto 4 R1 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 4 R1 left", 3, params.mLeftKeys);
+        assertEquals("6 key auto 4 R1 right", 1, params.mRightKeys);
+        assertEquals("6 key auto 4 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 4 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("6 key auto 4 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("6 key auto 4 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("6 key auto 4 R1 [5]", 0, params.getColumnPos(4));
+        assertEquals("6 key auto 4 R1 [6]", -1, params.getColumnPos(5));
+        assertEquals("6 key auto 4 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 4 R1 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //         [5] [6] ___|
+    // [4] [3] <1> [2] ___|
+    public void testLayout6KeyAuto4R2() {
+        MoreKeysKeyboardParams params = createParams(6, 4, XPOS_R2);
+        assertEquals("6 key auto 4 R2 columns", 4, params.mNumColumns);
+        assertEquals("6 key auto 4 R2 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 4 R2 left", 2, params.mLeftKeys);
+        assertEquals("6 key auto 4 R2 right", 2, params.mRightKeys);
+        assertEquals("6 key auto 4 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 4 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key auto 4 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("6 key auto 4 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("6 key auto 4 R2 [5]", 0, params.getColumnPos(4));
+        assertEquals("6 key auto 4 R2 [6]", 1, params.getColumnPos(5));
+        assertEquals("6 key auto 4 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 4 R2 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //         [6]
+    // [5] [3] <1> [2] [4]
+    public void testLayout6KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(6, 5, XPOS_M0);
+        assertEquals("6 key auto 5 M0 columns", 5, params.mNumColumns);
+        assertEquals("6 key auto 5 M0 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 5 M0 left", 2, params.mLeftKeys);
+        assertEquals("6 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("6 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("6 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("6 key auto 5 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("6 key auto 5 M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("6 key auto 5 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // |[6]
+    // |<1> [2] [3] [4] [5]
+    public void testLayout6KeyAuto5L0() {
+        MoreKeysKeyboardParams params = createParams(6, 5, XPOS_L0);
+        assertEquals("6 key auto 5 L0 columns", 5, params.mNumColumns);
+        assertEquals("6 key auto 5 L0 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 5 L0 left", 0, params.mLeftKeys);
+        assertEquals("6 key auto 5 L0 right", 5, params.mRightKeys);
+        assertEquals("6 key auto 5 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 5 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key auto 5 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("6 key auto 5 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("6 key auto 5 L0 [5]", 4, params.getColumnPos(4));
+        assertEquals("6 key auto 5 L0 [6]", 0, params.getColumnPos(5));
+        assertEquals("6 key auto 5 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [6]
+    // |___ <1> [2] [3] [4] [5]
+    public void testLayout6KeyAuto5L1() {
+        MoreKeysKeyboardParams params = createParams(6, 5, XPOS_L1);
+        assertEquals("6 key auto 5 L1 columns", 5, params.mNumColumns);
+        assertEquals("6 key auto 5 L1 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 5 L1 left", 0, params.mLeftKeys);
+        assertEquals("6 key auto 5 L1 right", 5, params.mRightKeys);
+        assertEquals("6 key auto 5 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 5 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key auto 5 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("6 key auto 5 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("6 key auto 5 L1 [5]", 4, params.getColumnPos(4));
+        assertEquals("6 key auto 5 L1 [6]", 0, params.getColumnPos(5));
+        assertEquals("6 key auto 5 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___     [6]
+    // |___ [3] <1> [2] [4] [5]
+    public void testLayout6KeyAuto5L2() {
+        MoreKeysKeyboardParams params = createParams(6, 5, XPOS_L2);
+        assertEquals("6 key auto 5 L2 columns", 5, params.mNumColumns);
+        assertEquals("6 key auto 5 L2 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 5 L2 left", 1, params.mLeftKeys);
+        assertEquals("6 key auto 5 L2 right", 4, params.mRightKeys);
+        assertEquals("6 key auto 5 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 5 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key auto 5 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("6 key auto 5 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("6 key auto 5 L2 [5]", 3, params.getColumnPos(4));
+        assertEquals("6 key auto 5 L2 [6]", 0, params.getColumnPos(5));
+        assertEquals("6 key auto 5 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //                 [6]|
+    // [5] [4] [3] [2] <1>|
+    public void testLayout6KeyAuto5R0() {
+        MoreKeysKeyboardParams params = createParams(6, 5, XPOS_R0);
+        assertEquals("6 key auto 5 R0 columns", 5, params.mNumColumns);
+        assertEquals("6 key auto 5 R0 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 5 R0 left", 4, params.mLeftKeys);
+        assertEquals("6 key auto 5 R0 right", 1, params.mRightKeys);
+        assertEquals("6 key auto 5 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 5 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("6 key auto 5 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("6 key auto 5 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("6 key auto 5 R0 [5]", -4, params.getColumnPos(4));
+        assertEquals("6 key auto 5 R0 [6]", 0, params.getColumnPos(5));
+        assertEquals("6 key auto 5 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    //                 [6] ___|
+    // [5] [4] [3] [2] <1> ___|
+    public void testLayout6KeyAuto5R1() {
+        MoreKeysKeyboardParams params = createParams(6, 5, XPOS_R1);
+        assertEquals("6 key auto 5 R1 columns", 5, params.mNumColumns);
+        assertEquals("6 key auto 5 R1 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 5 R1 left", 4, params.mLeftKeys);
+        assertEquals("6 key auto 5 R1 right", 1, params.mRightKeys);
+        assertEquals("6 key auto 5 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 5 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("6 key auto 5 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("6 key auto 5 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("6 key auto 5 R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("6 key auto 5 R1 [6]", 0, params.getColumnPos(5));
+        assertEquals("6 key auto 5 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    //             [6]     ___|
+    // [5] [4] [3] <1> [2] ___|
+    public void testLayout6KeyAuto5R2() {
+        MoreKeysKeyboardParams params = createParams(6, 5, XPOS_R2);
+        assertEquals("6 key auto 5 R2 columns", 5, params.mNumColumns);
+        assertEquals("6 key auto 5 R2 rows", 2, params.mNumRows);
+        assertEquals("6 key auto 5 R2 left", 3, params.mLeftKeys);
+        assertEquals("6 key auto 5 R2 right", 2, params.mRightKeys);
+        assertEquals("6 key auto 5 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("6 key auto 5 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("6 key auto 5 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("6 key auto 5 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("6 key auto 5 R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("6 key auto 5 R2 [6]", 0, params.getColumnPos(5));
+        assertEquals("6 key auto 5 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("6 key auto 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // |<1> [2] [3] [4] [5] [6] [7] ___ ___ ___|
+    public void testLayout7KeyAuto7L0() {
+        MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L0);
+        assertEquals("7 key auto 7 L0 columns", 7, params.mNumColumns);
+        assertEquals("7 key auto 7 L0 rows", 1, params.mNumRows);
+        assertEquals("7 key auto 7 L0 left", 0, params.mLeftKeys);
+        assertEquals("7 key auto 7 L0 right", 7, params.mRightKeys);
+        assertEquals("7 key auto 7 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 7 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 7 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("7 key auto 7 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("7 key auto 7 L0 [5]", 4, params.getColumnPos(4));
+        assertEquals("7 key auto 7 L0 [6]", 5, params.getColumnPos(5));
+        assertEquals("7 key auto 7 L0 [7]", 6, params.getColumnPos(6));
+        assertEquals("7 key auto 7 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 7 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ <1> [2] [3] [4] [5] [6] [7] ___ ___|
+    public void testLayout7KeyAuto7L1() {
+        MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L1);
+        assertEquals("7 key auto 7 L1 columns", 7, params.mNumColumns);
+        assertEquals("7 key auto 7 L1 rows", 1, params.mNumRows);
+        assertEquals("7 key auto 7 L1 left", 0, params.mLeftKeys);
+        assertEquals("7 key auto 7 L1 right", 7, params.mRightKeys);
+        assertEquals("7 key auto 7 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 7 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 7 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("7 key auto 7 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("7 key auto 7 L1 [5]", 4, params.getColumnPos(4));
+        assertEquals("7 key auto 7 L1 [6]", 5, params.getColumnPos(5));
+        assertEquals("7 key auto 7 L1 [7]", 6, params.getColumnPos(6));
+        assertEquals("7 key auto 7 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 7 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [3] <1> [2] [4] [5] [6] [7] ___ ___|
+    public void testLayout7KeyAuto7L2() {
+        MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L2);
+        assertEquals("7 key auto 7 L2 columns", 7, params.mNumColumns);
+        assertEquals("7 key auto 7 L2 rows", 1, params.mNumRows);
+        assertEquals("7 key auto 7 L2 left", 1, params.mLeftKeys);
+        assertEquals("7 key auto 7 L2 right", 6, params.mRightKeys);
+        assertEquals("7 key auto 7 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 7 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 7 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 7 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("7 key auto 7 L2 [5]", 3, params.getColumnPos(4));
+        assertEquals("7 key auto 7 L2 [6]", 4, params.getColumnPos(5));
+        assertEquals("7 key auto 7 L2 [7]", 5, params.getColumnPos(6));
+        assertEquals("7 key auto 7 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 7 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [5] [3] <1> [2] [4] [6] [7] ___ ___|
+    public void testLayout7KeyAuto7L3() {
+        MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L3);
+        assertEquals("7 key auto 7 L3 columns", 7, params.mNumColumns);
+        assertEquals("7 key auto 7 L3 rows", 1, params.mNumRows);
+        assertEquals("7 key auto 7 L3 left", 2, params.mLeftKeys);
+        assertEquals("7 key auto 7 L3 right", 5, params.mRightKeys);
+        assertEquals("7 key auto 7 L3 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 7 L3 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 7 L3 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 7 L3 [4]", 2, params.getColumnPos(3));
+        assertEquals("7 key auto 7 L3 [5]", -2, params.getColumnPos(4));
+        assertEquals("7 key auto 7 L3 [6]", 3, params.getColumnPos(5));
+        assertEquals("7 key auto 7 L3 [7]", 4, params.getColumnPos(6));
+        assertEquals("7 key auto 7 L3 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 7 L3 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [7] [5] [3] <1> [2] [4] [6] ___ ___|
+    public void testLayout7KeyAuto7M0() {
+        MoreKeysKeyboardParams params = createParams(7, 7, XPOS_M0);
+        assertEquals("7 key auto 7 M0 columns", 7, params.mNumColumns);
+        assertEquals("7 key auto 7 M0 rows", 1, params.mNumRows);
+        assertEquals("7 key auto 7 M0 left", 3, params.mLeftKeys);
+        assertEquals("7 key auto 7 M0 right", 4, params.mRightKeys);
+        assertEquals("7 key auto 7 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 7 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 7 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 7 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("7 key auto 7 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("7 key auto 7 M0 [6]", 3, params.getColumnPos(5));
+        assertEquals("7 key auto 7 M0 [7]", -3, params.getColumnPos(6));
+        assertEquals("7 key auto 7 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 7 M0 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [7] [5] [3] <1> [2] [4] [6] ___|
+    public void testLayout7KeyAuto7M1() {
+        MoreKeysKeyboardParams params = createParams(7, 7, XPOS_M1);
+        assertEquals("7 key auto 7 M1 columns", 7, params.mNumColumns);
+        assertEquals("7 key auto 7 M1 rows", 1, params.mNumRows);
+        assertEquals("7 key auto 7 M1 left", 3, params.mLeftKeys);
+        assertEquals("7 key auto 7 M1 right", 4, params.mRightKeys);
+        assertEquals("7 key auto 7 M1 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 7 M1 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 7 M1 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 7 M1 [4]", 2, params.getColumnPos(3));
+        assertEquals("7 key auto 7 M1 [5]", -2, params.getColumnPos(4));
+        assertEquals("7 key auto 7 M1 [6]", 3, params.getColumnPos(5));
+        assertEquals("7 key auto 7 M1 [7]", -3, params.getColumnPos(6));
+        assertEquals("7 key auto 7 M1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 7 M1 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [7] [6] [5] [3] <1> [2] [4] ___|
+    public void testLayout7KeyAuto7R3() {
+        MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R3);
+        assertEquals("7 key auto 7 R3 columns", 7, params.mNumColumns);
+        assertEquals("7 key auto 7 R3 rows", 1, params.mNumRows);
+        assertEquals("7 key auto 7 R3 left", 4, params.mLeftKeys);
+        assertEquals("7 key auto 7 R3 right", 3, params.mRightKeys);
+        assertEquals("7 key auto 7 R3 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 7 R3 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 7 R3 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 7 R3 [4]", 2, params.getColumnPos(3));
+        assertEquals("7 key auto 7 R3 [5]", -2, params.getColumnPos(4));
+        assertEquals("7 key auto 7 R3 [6]", -3, params.getColumnPos(5));
+        assertEquals("7 key auto 7 R3 [7]", -4, params.getColumnPos(6));
+        assertEquals("7 key auto 7 R3 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 7 R3 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [7] [6] [5] [4] [3] <1> [2] ___|
+    public void testLayout7KeyAuto7R2() {
+        MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R2);
+        assertEquals("7 key auto 7 R2 columns", 7, params.mNumColumns);
+        assertEquals("7 key auto 7 R2 rows", 1, params.mNumRows);
+        assertEquals("7 key auto 7 R2 left", 5, params.mLeftKeys);
+        assertEquals("7 key auto 7 R2 right", 2, params.mRightKeys);
+        assertEquals("7 key auto 7 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 7 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 7 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 7 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("7 key auto 7 R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("7 key auto 7 R2 [6]", -4, params.getColumnPos(5));
+        assertEquals("7 key auto 7 R2 [7]", -5, params.getColumnPos(6));
+        assertEquals("7 key auto 7 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 7 R2 default", WIDTH * 5, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [7] [6] [5] [4] [3] [2] <1> ___|
+    public void testLayout7KeyAuto7R1() {
+        MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R1);
+        assertEquals("7 key auto 7 R1 columns", 7, params.mNumColumns);
+        assertEquals("7 key auto 7 R1 rows", 1, params.mNumRows);
+        assertEquals("7 key auto 7 R1 left", 6, params.mLeftKeys);
+        assertEquals("7 key auto 7 R1 right", 1, params.mRightKeys);
+        assertEquals("7 key auto 7 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 7 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("7 key auto 7 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("7 key auto 7 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("7 key auto 7 R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("7 key auto 7 R1 [6]", -5, params.getColumnPos(5));
+        assertEquals("7 key auto 7 R1 [7]", -6, params.getColumnPos(6));
+        assertEquals("7 key auto 7 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 7 R1 default", WIDTH * 6, params.getDefaultKeyCoordX());
+    }
+
+    // |___ ___ [7] [6] [5] [4] [3] [2] <1>|
+    public void testLayout7KeyAuto7R0() {
+        MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R0);
+        assertEquals("7 key auto 7 R0 columns", 7, params.mNumColumns);
+        assertEquals("7 key auto 7 R0 rows", 1, params.mNumRows);
+        assertEquals("7 key auto 7 R0 left", 6, params.mLeftKeys);
+        assertEquals("7 key auto 7 R0 right", 1, params.mRightKeys);
+        assertEquals("7 key auto 7 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 7 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("7 key auto 7 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("7 key auto 7 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("7 key auto 7 R0 [5]", -4, params.getColumnPos(4));
+        assertEquals("7 key auto 7 R0 [6]", -5, params.getColumnPos(5));
+        assertEquals("7 key auto 7 R0 [7]", -6, params.getColumnPos(6));
+        assertEquals("7 key auto 7 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 7 R0 default", WIDTH * 6, params.getDefaultKeyCoordX());
+    }
+
+    //       [6] [7]
+    // [5] [3] <1> [2] [4]
+    public void testLayout7KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(7, 5, XPOS_M0);
+        assertEquals("7 key auto 5 M0 columns", 5, params.mNumColumns);
+        assertEquals("7 key auto 5 M0 rows", 2, params.mNumRows);
+        assertEquals("7 key auto 5 M0 left", 2, params.mLeftKeys);
+        assertEquals("7 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("7 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("7 key auto 5 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("7 key auto 5 M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("7 key auto 5 M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("7 key auto 5 M0 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("7 key auto 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // |[6] [7]
+    // |<1> [2] [3] [4] [5]
+    public void testLayout7KeyAuto5L0() {
+        MoreKeysKeyboardParams params = createParams(7, 5, XPOS_L0);
+        assertEquals("7 key auto 5 L0 columns", 5, params.mNumColumns);
+        assertEquals("7 key auto 5 L0 rows", 2, params.mNumRows);
+        assertEquals("7 key auto 5 L0 left", 0, params.mLeftKeys);
+        assertEquals("7 key auto 5 L0 right", 5, params.mRightKeys);
+        assertEquals("7 key auto 5 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 5 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 5 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("7 key auto 5 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("7 key auto 5 L0 [5]", 4, params.getColumnPos(4));
+        assertEquals("7 key auto 5 L0 [6]", 0, params.getColumnPos(5));
+        assertEquals("7 key auto 5 L0 [7]", 1, params.getColumnPos(6));
+        assertEquals("7 key auto 5 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [6] [7]
+    // |___ <1> [2] [3] [4] [5]
+    public void testLayout7KeyAuto5L1() {
+        MoreKeysKeyboardParams params = createParams(7, 5, XPOS_L1);
+        assertEquals("7 key auto 5 L1 columns", 5, params.mNumColumns);
+        assertEquals("7 key auto 5 L1 rows", 2, params.mNumRows);
+        assertEquals("7 key auto 5 L1 left", 0, params.mLeftKeys);
+        assertEquals("7 key auto 5 L1 right", 5, params.mRightKeys);
+        assertEquals("7 key auto 5 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 5 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 5 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("7 key auto 5 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("7 key auto 5 L1 [5]", 4, params.getColumnPos(4));
+        assertEquals("7 key auto 5 L1 [6]", 0, params.getColumnPos(5));
+        assertEquals("7 key auto 5 L1 [7]", 1, params.getColumnPos(6));
+        assertEquals("7 key auto 5 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___   [6] [7]
+    // |___ [3] <1> [2] [4] [5]
+    public void testLayout7KeyAuto5L2() {
+        MoreKeysKeyboardParams params = createParams(7, 5, XPOS_L2);
+        assertEquals("7 key auto 5 L2 columns", 5, params.mNumColumns);
+        assertEquals("7 key auto 5 L2 rows", 2, params.mNumRows);
+        assertEquals("7 key auto 5 L2 left", 1, params.mLeftKeys);
+        assertEquals("7 key auto 5 L2 right", 4, params.mRightKeys);
+        assertEquals("7 key auto 5 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 5 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 5 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 5 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("7 key auto 5 L2 [5]", 3, params.getColumnPos(4));
+        assertEquals("7 key auto 5 L2 [6]", 0, params.getColumnPos(5));
+        assertEquals("7 key auto 5 L2 [7]", 1, params.getColumnPos(6));
+        assertEquals("7 key auto 5 L2 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("7 key auto 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //             [7] [6]|
+    // [5] [4] [3] [2] <1>|
+    public void testLayout7KeyAuto5R0() {
+        MoreKeysKeyboardParams params = createParams(7, 5, XPOS_R0);
+        assertEquals("7 key auto 5 R0 columns", 5, params.mNumColumns);
+        assertEquals("7 key auto 5 R0 rows", 2, params.mNumRows);
+        assertEquals("7 key auto 5 R0 left", 4, params.mLeftKeys);
+        assertEquals("7 key auto 5 R0 right", 1, params.mRightKeys);
+        assertEquals("7 key auto 5 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 5 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("7 key auto 5 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("7 key auto 5 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("7 key auto 5 R0 [5]", -4, params.getColumnPos(4));
+        assertEquals("7 key auto 5 R0 [6]", 0, params.getColumnPos(5));
+        assertEquals("7 key auto 5 R0 [7]", -1, params.getColumnPos(6));
+        assertEquals("7 key auto 5 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    //             [7] [6] ___|
+    // [5] [4] [3] [2] <1> ___|
+    public void testLayout7KeyAuto5R1() {
+        MoreKeysKeyboardParams params = createParams(7, 5, XPOS_R1);
+        assertEquals("7 key auto 5 R1 columns", 5, params.mNumColumns);
+        assertEquals("7 key auto 5 R1 rows", 2, params.mNumRows);
+        assertEquals("7 key auto 5 R1 left", 4, params.mLeftKeys);
+        assertEquals("7 key auto 5 R1 right", 1, params.mRightKeys);
+        assertEquals("7 key auto 5 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 5 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("7 key auto 5 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("7 key auto 5 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("7 key auto 5 R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("7 key auto 5 R1 [6]", 0, params.getColumnPos(5));
+        assertEquals("7 key auto 5 R1 [7]", -1, params.getColumnPos(6));
+        assertEquals("7 key auto 5 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    //           [6] [7]   ___|
+    // [5] [4] [3] <1> [2] ___|
+    public void testLayout7KeyAuto5R2() {
+        MoreKeysKeyboardParams params = createParams(7, 5, XPOS_R2);
+        assertEquals("7 key auto 5 R2 columns", 5, params.mNumColumns);
+        assertEquals("7 key auto 5 R2 rows", 2, params.mNumRows);
+        assertEquals("7 key auto 5 R2 left", 3, params.mLeftKeys);
+        assertEquals("7 key auto 5 R2 right", 2, params.mRightKeys);
+        assertEquals("7 key auto 5 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 5 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 5 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 5 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("7 key auto 5 R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("7 key auto 5 R2 [6]", 0, params.getColumnPos(5));
+        assertEquals("7 key auto 5 R2 [7]", 1, params.getColumnPos(6));
+        assertEquals("7 key auto 5 R2 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("7 key auto 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //     [7]
+    // [6] [4] [5]
+    // [3] <1> [2]
+    public void testLayout7KeyAuto3M0() {
+        MoreKeysKeyboardParams params = createParams(7, 3, XPOS_M0);
+        assertEquals("7 key auto 3 M0 columns", 3, params.mNumColumns);
+        assertEquals("7 key auto 3 M0 rows", 3, params.mNumRows);
+        assertEquals("7 key auto 3 M0 left", 1, params.mLeftKeys);
+        assertEquals("7 key auto 3 M0 right", 2, params.mRightKeys);
+        assertEquals("7 key auto 3 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 3 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 3 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 3 M0 [4]", 0, params.getColumnPos(3));
+        assertEquals("7 key auto 3 M0 [5]", 1, params.getColumnPos(4));
+        assertEquals("7 key auto 3 M0 [6]", -1, params.getColumnPos(5));
+        assertEquals("7 key auto 3 M0 [7]", 0, params.getColumnPos(6));
+        assertEquals("7 key auto 3 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 3 M0 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // |[7]
+    // |[4] [5] [6]
+    // |<1> [2] [3]
+    public void testLayout7KeyAuto3L0() {
+        MoreKeysKeyboardParams params = createParams(7, 3, XPOS_L0);
+        assertEquals("7 key auto 3 L0 columns", 3, params.mNumColumns);
+        assertEquals("7 key auto 3 L0 rows", 3, params.mNumRows);
+        assertEquals("7 key auto 3 L0 left", 0, params.mLeftKeys);
+        assertEquals("7 key auto 3 L0 right", 3, params.mRightKeys);
+        assertEquals("7 key auto 3 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 3 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 3 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("7 key auto 3 L0 [4]", 0, params.getColumnPos(3));
+        assertEquals("7 key auto 3 L0 [5]", 1, params.getColumnPos(4));
+        assertEquals("7 key auto 3 L0 [6]", 2, params.getColumnPos(5));
+        assertEquals("7 key auto 3 L0 [7]", 0, params.getColumnPos(6));
+        assertEquals("7 key auto 3 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 3 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [7]
+    // |___ [4] [5] [6]
+    // |___ <1> [2] [3]
+    public void testLayout7KeyAuto3L1() {
+        MoreKeysKeyboardParams params = createParams(7, 3, XPOS_L1);
+        assertEquals("7 key auto 3 L1 columns", 3, params.mNumColumns);
+        assertEquals("7 key auto 3 L1 rows", 3, params.mNumRows);
+        assertEquals("7 key auto 3 L1 left", 0, params.mLeftKeys);
+        assertEquals("7 key auto 3 L1 right", 3, params.mRightKeys);
+        assertEquals("7 key auto 3 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 3 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 3 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("7 key auto 3 L1 [4]", 0, params.getColumnPos(3));
+        assertEquals("7 key auto 3 L1 [5]", 1, params.getColumnPos(4));
+        assertEquals("7 key auto 3 L1 [6]", 2, params.getColumnPos(5));
+        assertEquals("7 key auto 3 L1 [7]", 0, params.getColumnPos(6));
+        assertEquals("7 key auto 3 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 3 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___     [7]
+    // |___ [6] [4] [5]
+    // |___ [3] <1> [2]
+    public void testLayout7KeyAuto3L2() {
+        MoreKeysKeyboardParams params = createParams(7, 3, XPOS_L2);
+        assertEquals("7 key auto 3 L2 columns", 3, params.mNumColumns);
+        assertEquals("7 key auto 3 L2 rows", 3, params.mNumRows);
+        assertEquals("7 key auto 3 L2 left", 1, params.mLeftKeys);
+        assertEquals("7 key auto 3 L2 right", 2, params.mRightKeys);
+        assertEquals("7 key auto 3 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 3 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 3 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 3 L2 [4]", 0, params.getColumnPos(3));
+        assertEquals("7 key auto 3 L2 [5]", 1, params.getColumnPos(4));
+        assertEquals("7 key auto 3 L2 [6]", -1, params.getColumnPos(5));
+        assertEquals("7 key auto 3 L2 [7]", 0, params.getColumnPos(6));
+        assertEquals("7 key auto 3 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 3 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //         [7]|
+    // [6] [5] [4]|
+    // [3] [2] <1>|
+    public void testLayout7KeyAuto3R0() {
+        MoreKeysKeyboardParams params = createParams(7, 3, XPOS_R0);
+        assertEquals("7 key auto 3 R0 columns", 3, params.mNumColumns);
+        assertEquals("7 key auto 3 R0 rows", 3, params.mNumRows);
+        assertEquals("7 key auto 3 R0 left", 2, params.mLeftKeys);
+        assertEquals("7 key auto 3 R0 right", 1, params.mRightKeys);
+        assertEquals("7 key auto 3 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 3 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("7 key auto 3 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("7 key auto 3 R0 [4]", 0, params.getColumnPos(3));
+        assertEquals("7 key auto 3 R0 [5]", -1, params.getColumnPos(4));
+        assertEquals("7 key auto 3 R0 [6]", -2, params.getColumnPos(5));
+        assertEquals("7 key auto 3 R0 [7]", 0, params.getColumnPos(6));
+        assertEquals("7 key auto 3 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 3 R0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //         [7] ___|
+    // [6] [5] [4] ___|
+    // [3] [2] <1> ___|
+    public void testLayout7KeyAuto3R1() {
+        MoreKeysKeyboardParams params = createParams(7, 3, XPOS_R1);
+        assertEquals("7 key auto 3 R1 columns", 3, params.mNumColumns);
+        assertEquals("7 key auto 3 R1 rows", 3, params.mNumRows);
+        assertEquals("7 key auto 3 R1 left", 2, params.mLeftKeys);
+        assertEquals("7 key auto 3 R1 right", 1, params.mRightKeys);
+        assertEquals("7 key auto 3 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 3 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("7 key auto 3 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("7 key auto 3 R1 [4]", 0, params.getColumnPos(3));
+        assertEquals("7 key auto 3 R1 [5]", -1, params.getColumnPos(4));
+        assertEquals("7 key auto 3 R1 [6]", -2, params.getColumnPos(5));
+        assertEquals("7 key auto 3 R1 [7]", 0, params.getColumnPos(6));
+        assertEquals("7 key auto 3 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 3 R1 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //     [7]     ___|
+    // [6] [4] [5] ___|
+    // [3] <1> [2] ___|
+    public void testLayout7KeyAuto3R2() {
+        MoreKeysKeyboardParams params = createParams(7, 3, XPOS_R2);
+        assertEquals("7 key auto 3 R2 columns", 3, params.mNumColumns);
+        assertEquals("7 key auto 3 R2 rows", 3, params.mNumRows);
+        assertEquals("7 key auto 3 R2 left", 1, params.mLeftKeys);
+        assertEquals("7 key auto 3 R2 right", 2, params.mRightKeys);
+        assertEquals("7 key auto 3 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("7 key auto 3 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("7 key auto 3 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("7 key auto 3 R2 [4]", 0, params.getColumnPos(3));
+        assertEquals("7 key auto 3 R2 [5]", 1, params.getColumnPos(4));
+        assertEquals("7 key auto 3 R2 [6]", -1, params.getColumnPos(5));
+        assertEquals("7 key auto 3 R2 [7]", 0, params.getColumnPos(6));
+        assertEquals("7 key auto 3 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("7 key auto 3 R2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //     [8] [6] [7]
+    // [5] [3] <1> [2] [4]
+    public void testLayout8KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(8, 5, XPOS_M0);
+        assertEquals("8 key auto 5 M0 columns", 5, params.mNumColumns);
+        assertEquals("8 key auto 5 M0 rows", 2, params.mNumRows);
+        assertEquals("8 key auto 5 M0 left", 2, params.mLeftKeys);
+        assertEquals("8 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("8 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("8 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("8 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("8 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("8 key auto 5 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("8 key auto 5 M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("8 key auto 5 M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("8 key auto 5 M0 [8]", -1, params.getColumnPos(7));
+        assertEquals("8 key auto 5 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key auto 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // |[6] [7] [8]
+    // |<1> [2] [3] [4] [5]
+    public void testLayout8KeyAuto5L0() {
+        MoreKeysKeyboardParams params = createParams(8, 5, XPOS_L0);
+        assertEquals("8 key auto 5 L0 columns", 5, params.mNumColumns);
+        assertEquals("8 key auto 5 L0 rows", 2, params.mNumRows);
+        assertEquals("8 key auto 5 L0 left", 0, params.mLeftKeys);
+        assertEquals("8 key auto 5 L0 right", 5, params.mRightKeys);
+        assertEquals("8 key auto 5 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("8 key auto 5 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("8 key auto 5 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("8 key auto 5 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("8 key auto 5 L0 [5]", 4, params.getColumnPos(4));
+        assertEquals("8 key auto 5 L0 [6]", 0, params.getColumnPos(5));
+        assertEquals("8 key auto 5 L0 [7]", 1, params.getColumnPos(6));
+        assertEquals("8 key auto 5 L0 [8]", 2, params.getColumnPos(7));
+        assertEquals("8 key auto 5 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key auto 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [6] [7] [8]
+    // |___ <1> [2] [3] [4] [5]
+    public void testLayout8KeyAuto5L1() {
+        MoreKeysKeyboardParams params = createParams(8, 5, XPOS_L1);
+        assertEquals("8 key auto 5 L1 columns", 5, params.mNumColumns);
+        assertEquals("8 key auto 5 L1 rows", 2, params.mNumRows);
+        assertEquals("8 key auto 5 L1 left", 0, params.mLeftKeys);
+        assertEquals("8 key auto 5 L1 right", 5, params.mRightKeys);
+        assertEquals("8 key auto 5 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("8 key auto 5 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("8 key auto 5 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("8 key auto 5 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("8 key auto 5 L1 [5]", 4, params.getColumnPos(4));
+        assertEquals("8 key auto 5 L1 [6]", 0, params.getColumnPos(5));
+        assertEquals("8 key auto 5 L1 [7]", 1, params.getColumnPos(6));
+        assertEquals("8 key auto 5 L1 [8]", 2, params.getColumnPos(7));
+        assertEquals("8 key auto 5 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key auto 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [8] [6] [7]
+    // |___ [3] <1> [2] [4] [5]
+    public void testLayout8KeyAuto5L2() {
+        MoreKeysKeyboardParams params = createParams(8, 5, XPOS_L2);
+        assertEquals("8 key auto 5 L2 columns", 5, params.mNumColumns);
+        assertEquals("8 key auto 5 L2 rows", 2, params.mNumRows);
+        assertEquals("8 key auto 5 L2 left", 1, params.mLeftKeys);
+        assertEquals("8 key auto 5 L2 right", 4, params.mRightKeys);
+        assertEquals("8 key auto 5 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("8 key auto 5 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("8 key auto 5 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("8 key auto 5 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("8 key auto 5 L2 [5]", 3, params.getColumnPos(4));
+        assertEquals("8 key auto 5 L2 [6]", 0, params.getColumnPos(5));
+        assertEquals("8 key auto 5 L2 [7]", 1, params.getColumnPos(6));
+        assertEquals("8 key auto 5 L2 [8]", -1, params.getColumnPos(7));
+        assertEquals("8 key auto 5 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key auto 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //         [8] [7] [6]|
+    // [5] [4] [3] [2] <1>|
+    public void testLayout8KeyAuto5R0() {
+        MoreKeysKeyboardParams params = createParams(8, 5, XPOS_R0);
+        assertEquals("8 key auto 5 R0 columns", 5, params.mNumColumns);
+        assertEquals("8 key auto 5 R0 rows", 2, params.mNumRows);
+        assertEquals("8 key auto 5 R0 left", 4, params.mLeftKeys);
+        assertEquals("8 key auto 5 R0 right", 1, params.mRightKeys);
+        assertEquals("8 key auto 5 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("8 key auto 5 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("8 key auto 5 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("8 key auto 5 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("8 key auto 5 R0 [5]", -4, params.getColumnPos(4));
+        assertEquals("8 key auto 5 R0 [6]", 0, params.getColumnPos(5));
+        assertEquals("8 key auto 5 R0 [7]", -1, params.getColumnPos(6));
+        assertEquals("8 key auto 5 R0 [8]", -2, params.getColumnPos(7));
+        assertEquals("8 key auto 5 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key auto 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    //         [8] [7] [6] ___|
+    // [5] [4] [3] [2] <1> ___|
+    public void testLayout8KeyAuto5R1() {
+        MoreKeysKeyboardParams params = createParams(8, 5, XPOS_R1);
+        assertEquals("8 key auto 5 R1 columns", 5, params.mNumColumns);
+        assertEquals("8 key auto 5 R1 rows", 2, params.mNumRows);
+        assertEquals("8 key auto 5 R1 left", 4, params.mLeftKeys);
+        assertEquals("8 key auto 5 R1 right", 1, params.mRightKeys);
+        assertEquals("8 key auto 5 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("8 key auto 5 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("8 key auto 5 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("8 key auto 5 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("8 key auto 5 R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("8 key auto 5 R1 [6]", 0, params.getColumnPos(5));
+        assertEquals("8 key auto 5 R1 [7]", -1, params.getColumnPos(6));
+        assertEquals("8 key auto 5 R1 [8]", -2, params.getColumnPos(7));
+        assertEquals("8 key auto 5 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key auto 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    //         [8] [6] [7] ___|
+    // [5] [4] [3] <1> [2] ___|
+    public void testLayout8KeyAuto5R2() {
+        MoreKeysKeyboardParams params = createParams(8, 5, XPOS_R2);
+        assertEquals("8 key auto 5 R2 columns", 5, params.mNumColumns);
+        assertEquals("8 key auto 5 R2 rows", 2, params.mNumRows);
+        assertEquals("8 key auto 5 R2 left", 3, params.mLeftKeys);
+        assertEquals("8 key auto 5 R2 right", 2, params.mRightKeys);
+        assertEquals("8 key auto 5 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("8 key auto 5 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("8 key auto 5 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("8 key auto 5 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("8 key auto 5 R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("8 key auto 5 R2 [6]", 0, params.getColumnPos(5));
+        assertEquals("8 key auto 5 R2 [7]", 1, params.getColumnPos(6));
+        assertEquals("8 key auto 5 R2 [8]", -1, params.getColumnPos(7));
+        assertEquals("8 key auto 5 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("8 key auto 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //   [8] [6] [7] [9]
+    // [5] [3] <1> [2] [4]
+    public void testLayout9KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(9, 5, XPOS_M0);
+        assertEquals("9 key auto 5 M0 columns", 5, params.mNumColumns);
+        assertEquals("9 key auto 5 M0 rows", 2, params.mNumRows);
+        assertEquals("9 key auto 5 M0 left", 2, params.mLeftKeys);
+        assertEquals("9 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("9 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("9 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("9 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("9 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("9 key auto 5 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("9 key auto 5 M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key auto 5 M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("9 key auto 5 M0 [8]", -1, params.getColumnPos(7));
+        assertEquals("9 key auto 5 M0 [9]", 2, params.getColumnPos(8));
+        assertEquals("9 key auto 5 M0 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("9 key auto 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // |[6] [7] [8] [9]
+    // |<1> [2] [3] [4] [5]
+    public void testLayout9KeyAuto5L0() {
+        MoreKeysKeyboardParams params = createParams(9, 5, XPOS_L0);
+        assertEquals("9 key auto 5 L0 columns", 5, params.mNumColumns);
+        assertEquals("9 key auto 5 L0 rows", 2, params.mNumRows);
+        assertEquals("9 key auto 5 L0 left", 0, params.mLeftKeys);
+        assertEquals("9 key auto 5 L0 right", 5, params.mRightKeys);
+        assertEquals("9 key auto 5 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("9 key auto 5 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("9 key auto 5 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("9 key auto 5 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("9 key auto 5 L0 [5]", 4, params.getColumnPos(4));
+        assertEquals("9 key auto 5 L0 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key auto 5 L0 [7]", 1, params.getColumnPos(6));
+        assertEquals("9 key auto 5 L0 [8]", 2, params.getColumnPos(7));
+        assertEquals("9 key auto 5 L0 [9]", 3, params.getColumnPos(8));
+        assertEquals("9 key auto 5 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("9 key auto 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [6] [7] [8] [9]
+    // |___ <1> [2] [3] [4] [5]
+    public void testLayout9KeyAuto5L1() {
+        MoreKeysKeyboardParams params = createParams(9, 5, XPOS_L1);
+        assertEquals("9 key auto 5 L1 columns", 5, params.mNumColumns);
+        assertEquals("9 key auto 5 L1 rows", 2, params.mNumRows);
+        assertEquals("9 key auto 5 L1 left", 0, params.mLeftKeys);
+        assertEquals("9 key auto 5 L1 right", 5, params.mRightKeys);
+        assertEquals("9 key auto 5 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("9 key auto 5 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("9 key auto 5 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("9 key auto 5 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("9 key auto 5 L1 [5]", 4, params.getColumnPos(4));
+        assertEquals("9 key auto 5 L1 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key auto 5 L1 [7]", 1, params.getColumnPos(6));
+        assertEquals("9 key auto 5 L1 [8]", 2, params.getColumnPos(7));
+        assertEquals("9 key auto 5 L1 [9]", 3, params.getColumnPos(8));
+        assertEquals("9 key auto 5 L1 adjust",0, params.mTopRowAdjustment);
+        assertEquals("9 key auto 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___   [6] [7] [8] [9]
+    // |___ [3] <1> [2] [4] [5]
+    public void testLayout9KeyAuto5L2() {
+        MoreKeysKeyboardParams params = createParams(9, 5, XPOS_L2);
+        assertEquals("9 key auto 5 L2 columns", 5, params.mNumColumns);
+        assertEquals("9 key auto 5 L2 rows", 2, params.mNumRows);
+        assertEquals("9 key auto 5 L2 left", 1, params.mLeftKeys);
+        assertEquals("9 key auto 5 L2 right", 4, params.mRightKeys);
+        assertEquals("9 key auto 5 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("9 key auto 5 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("9 key auto 5 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("9 key auto 5 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("9 key auto 5 L2 [5]", 3, params.getColumnPos(4));
+        assertEquals("9 key auto 5 L2 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key auto 5 L2 [7]", 1, params.getColumnPos(6));
+        assertEquals("9 key auto 5 L2 [8]", 2, params.getColumnPos(7));
+        assertEquals("9 key auto 5 L2 [9]", 3, params.getColumnPos(8));
+        assertEquals("9 key auto 5 L2 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("9 key auto 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    //     [9] [8] [7] [6]|
+    // [5] [4] [3] [2] <1>|
+    public void testLayout9KeyAuto5R0() {
+        MoreKeysKeyboardParams params = createParams(9, 5, XPOS_R0);
+        assertEquals("9 key auto 5 R0 columns", 5, params.mNumColumns);
+        assertEquals("9 key auto 5 R0 rows", 2, params.mNumRows);
+        assertEquals("9 key auto 5 R0 left", 4, params.mLeftKeys);
+        assertEquals("9 key auto 5 R0 right", 1, params.mRightKeys);
+        assertEquals("9 key auto 5 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("9 key auto 5 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("9 key auto 5 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("9 key auto 5 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("9 key auto 5 R0 [5]", -4, params.getColumnPos(4));
+        assertEquals("9 key auto 5 R0 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key auto 5 R0 [7]", -1, params.getColumnPos(6));
+        assertEquals("9 key auto 5 R0 [8]", -2, params.getColumnPos(7));
+        assertEquals("9 key auto 5 R0 [9]", -3, params.getColumnPos(8));
+        assertEquals("9 key auto 5 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("9 key auto 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    //     [9] [8] [7] [6] ___|
+    // [5] [4] [3] [2] <1> ___|
+    public void testLayout9KeyAuto5R1() {
+        MoreKeysKeyboardParams params = createParams(9, 5, XPOS_R1);
+        assertEquals("9 key auto 5 R1 columns", 5, params.mNumColumns);
+        assertEquals("9 key auto 5 R1 rows", 2, params.mNumRows);
+        assertEquals("9 key auto 5 R1 left", 4, params.mLeftKeys);
+        assertEquals("9 key auto 5 R1 right", 1, params.mRightKeys);
+        assertEquals("9 key auto 5 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("9 key auto 5 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("9 key auto 5 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("9 key auto 5 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("9 key auto 5 R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("9 key auto 5 R1 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key auto 5 R1 [7]", -1, params.getColumnPos(6));
+        assertEquals("9 key auto 5 R1 [8]", -2, params.getColumnPos(7));
+        assertEquals("9 key auto 5 R1 [9]", -3, params.getColumnPos(8));
+        assertEquals("9 key auto 5 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("9 key auto 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    //   [9] [8] [6] [7]   ___|
+    // [5] [4] [3] <1> [2] ___|
+    public void testLayout9KeyAuto5R2() {
+        MoreKeysKeyboardParams params = createParams(9, 5, XPOS_R2);
+        assertEquals("9 key auto 5 R2 columns", 5, params.mNumColumns);
+        assertEquals("9 key auto 5 R2 rows", 2, params.mNumRows);
+        assertEquals("9 key auto 5 R2 left", 3, params.mLeftKeys);
+        assertEquals("9 key auto 5 R2 right", 2, params.mRightKeys);
+        assertEquals("9 key auto 5 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("9 key auto 5 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("9 key auto 5 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("9 key auto 5 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("9 key auto 5 R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("9 key auto 5 R2 [6]", 0, params.getColumnPos(5));
+        assertEquals("9 key auto 5 R2 [7]", 1, params.getColumnPos(6));
+        assertEquals("9 key auto 5 R2 [8]", -1, params.getColumnPos(7));
+        assertEquals("9 key auto 5 R2 [9]", -2, params.getColumnPos(8));
+        assertEquals("9 key auto 5 R2 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("9 key auto 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    // [A] [8] [6] [7] [9]
+    // [5] [3] <1> [2] [4]
+    public void testLayout10KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(10, 5, XPOS_M0);
+        assertEquals("10 key auto 5 M0 columns", 5, params.mNumColumns);
+        assertEquals("10 key auto 5 M0 rows", 2, params.mNumRows);
+        assertEquals("10 key auto 5 M0 left", 2, params.mLeftKeys);
+        assertEquals("10 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("10 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("10 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("10 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("10 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("10 key auto 5 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("10 key auto 5 M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key auto 5 M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("10 key auto 5 M0 [8]", -1, params.getColumnPos(7));
+        assertEquals("10 key auto 5 M0 [9]", 2, params.getColumnPos(8));
+        assertEquals("10 key auto 5 M0 [A]", -2, params.getColumnPos(9));
+        assertEquals("10 key auto 5 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key auto 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    // |[6] [7] [8] [9] [A]
+    // |<1> [2] [3] [4] [5]
+    public void testLayout10KeyAuto5L0() {
+        MoreKeysKeyboardParams params = createParams(10, 5, XPOS_L0);
+        assertEquals("10 key auto 5 L0 columns", 5, params.mNumColumns);
+        assertEquals("10 key auto 5 L0 rows", 2, params.mNumRows);
+        assertEquals("10 key auto 5 L0 left", 0, params.mLeftKeys);
+        assertEquals("10 key auto 5 L0 right", 5, params.mRightKeys);
+        assertEquals("10 key auto 5 L0 <1>", 0, params.getColumnPos(0));
+        assertEquals("10 key auto 5 L0 [2]", 1, params.getColumnPos(1));
+        assertEquals("10 key auto 5 L0 [3]", 2, params.getColumnPos(2));
+        assertEquals("10 key auto 5 L0 [4]", 3, params.getColumnPos(3));
+        assertEquals("10 key auto 5 L0 [5]", 4, params.getColumnPos(4));
+        assertEquals("10 key auto 5 L0 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key auto 5 L0 [7]", 1, params.getColumnPos(6));
+        assertEquals("10 key auto 5 L0 [8]", 2, params.getColumnPos(7));
+        assertEquals("10 key auto 5 L0 [9]", 3, params.getColumnPos(8));
+        assertEquals("10 key auto 5 L0 [A]", 4, params.getColumnPos(9));
+        assertEquals("10 key auto 5 L0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key auto 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [6] [7] [8] [9] [A]
+    // |___ <1> [2] [3] [4] [5]
+    public void testLayout10KeyAuto5L1() {
+        MoreKeysKeyboardParams params = createParams(10, 5, XPOS_L1);
+        assertEquals("10 key auto 5 L1 columns", 5, params.mNumColumns);
+        assertEquals("10 key auto 5 L1 rows", 2, params.mNumRows);
+        assertEquals("10 key auto 5 L1 left", 0, params.mLeftKeys);
+        assertEquals("10 key auto 5 L1 right", 5, params.mRightKeys);
+        assertEquals("10 key auto 5 L1 <1>", 0, params.getColumnPos(0));
+        assertEquals("10 key auto 5 L1 [2]", 1, params.getColumnPos(1));
+        assertEquals("10 key auto 5 L1 [3]", 2, params.getColumnPos(2));
+        assertEquals("10 key auto 5 L1 [4]", 3, params.getColumnPos(3));
+        assertEquals("10 key auto 5 L1 [5]", 4, params.getColumnPos(4));
+        assertEquals("10 key auto 5 L1 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key auto 5 L1 [7]", 1, params.getColumnPos(6));
+        assertEquals("10 key auto 5 L1 [8]", 2, params.getColumnPos(7));
+        assertEquals("10 key auto 5 L1 [9]", 3, params.getColumnPos(8));
+        assertEquals("10 key auto 5 L1 [A]", 4, params.getColumnPos(9));
+        assertEquals("10 key auto 5 L1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key auto 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX());
+    }
+
+    // |___ [8] [6] [7] [9] [A]
+    // |___ [3] <1> [2] [4] [5]
+    public void testLayout10KeyAuto5L2() {
+        MoreKeysKeyboardParams params = createParams(10, 5, XPOS_L2);
+        assertEquals("10 key auto 5 L2 columns", 5, params.mNumColumns);
+        assertEquals("10 key auto 5 L2 rows", 2, params.mNumRows);
+        assertEquals("10 key auto 5 L2 left", 1, params.mLeftKeys);
+        assertEquals("10 key auto 5 L2 right", 4, params.mRightKeys);
+        assertEquals("10 key auto 5 L2 <1>", 0, params.getColumnPos(0));
+        assertEquals("10 key auto 5 L2 [2]", 1, params.getColumnPos(1));
+        assertEquals("10 key auto 5 L2 [3]", -1, params.getColumnPos(2));
+        assertEquals("10 key auto 5 L2 [4]", 2, params.getColumnPos(3));
+        assertEquals("10 key auto 5 L2 [5]", 3, params.getColumnPos(4));
+        assertEquals("10 key auto 5 L2 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key auto 5 L2 [7]", 1, params.getColumnPos(6));
+        assertEquals("10 key auto 5 L2 [8]", -1, params.getColumnPos(7));
+        assertEquals("10 key auto 5 L2 [9]", 2, params.getColumnPos(8));
+        assertEquals("10 key auto 5 L2 [A]", 3, params.getColumnPos(9));
+        assertEquals("10 key auto 5 L2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key auto 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX());
+    }
+
+    // [A] [9] [8] [7] [6]|
+    // [5] [4] [3] [2] <1>|
+    public void testLayout10KeyAuto5R0() {
+        MoreKeysKeyboardParams params = createParams(10, 5, XPOS_R0);
+        assertEquals("10 key auto 5 R0 columns", 5, params.mNumColumns);
+        assertEquals("10 key auto 5 R0 rows", 2, params.mNumRows);
+        assertEquals("10 key auto 5 R0 left", 4, params.mLeftKeys);
+        assertEquals("10 key auto 5 R0 right", 1, params.mRightKeys);
+        assertEquals("10 key auto 5 R0 <1>", 0, params.getColumnPos(0));
+        assertEquals("10 key auto 5 R0 [2]", -1, params.getColumnPos(1));
+        assertEquals("10 key auto 5 R0 [3]", -2, params.getColumnPos(2));
+        assertEquals("10 key auto 5 R0 [4]", -3, params.getColumnPos(3));
+        assertEquals("10 key auto 5 R0 [5]", -4, params.getColumnPos(4));
+        assertEquals("10 key auto 5 R0 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key auto 5 R0 [7]", -1, params.getColumnPos(6));
+        assertEquals("10 key auto 5 R0 [8]", -2, params.getColumnPos(7));
+        assertEquals("10 key auto 5 R0 [9]", -3, params.getColumnPos(8));
+        assertEquals("10 key auto 5 R0 [A]", -4, params.getColumnPos(9));
+        assertEquals("10 key auto 5 R0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key auto 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    // [A] [9] [8] [7] [6] ___|
+    // [5] [4] [3] [2] <1> ___|
+    public void testLayout10KeyAuto5R1() {
+        MoreKeysKeyboardParams params = createParams(10, 5, XPOS_R1);
+        assertEquals("10 key auto 5 R1 columns", 5, params.mNumColumns);
+        assertEquals("10 key auto 5 R1 rows", 2, params.mNumRows);
+        assertEquals("10 key auto 5 R1 left", 4, params.mLeftKeys);
+        assertEquals("10 key auto 5 R1 right", 1, params.mRightKeys);
+        assertEquals("10 key auto 5 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("10 key auto 5 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("10 key auto 5 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("10 key auto 5 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("10 key auto 5 R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("10 key auto 5 R1 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key auto 5 R1 [7]", -1, params.getColumnPos(6));
+        assertEquals("10 key auto 5 R1 [8]", -2, params.getColumnPos(7));
+        assertEquals("10 key auto 5 R1 [9]", -3, params.getColumnPos(8));
+        assertEquals("10 key auto 5 R1 [A]", -4, params.getColumnPos(9));
+        assertEquals("10 key auto 5 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key auto 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX());
+    }
+
+    // [A] [9] [8] [6] [7] ___|
+    // [5] [4] [3] <1> [2] ___|
+    public void testLayout10KeyAuto5R2() {
+        MoreKeysKeyboardParams params = createParams(10, 5, XPOS_R2);
+        assertEquals("10 key auto 5 R2 columns", 5, params.mNumColumns);
+        assertEquals("10 key auto 5 R2 rows", 2, params.mNumRows);
+        assertEquals("10 key auto 5 R2 left", 3, params.mLeftKeys);
+        assertEquals("10 key auto 5 R2 right", 2, params.mRightKeys);
+        assertEquals("10 key auto 5 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("10 key auto 5 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("10 key auto 5 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("10 key auto 5 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("10 key auto 5 R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("10 key auto 5 R2 [6]", 0, params.getColumnPos(5));
+        assertEquals("10 key auto 5 R2 [7]", 1, params.getColumnPos(6));
+        assertEquals("10 key auto 5 R2 [8]", -1, params.getColumnPos(7));
+        assertEquals("10 key auto 5 R2 [9]", -2, params.getColumnPos(8));
+        assertEquals("10 key auto 5 R2 [A]", -3, params.getColumnPos(9));
+        assertEquals("10 key auto 5 R2 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("10 key auto 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX());
+    }
+
+    //         [B]
+    // [A] [8] [6] [7] [9]
+    // [5] [3] <1> [2] [4]
+    public void testLayout11KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(11, 5, XPOS_M0);
+        assertEquals("11 key auto 5 M0 columns", 5, params.mNumColumns);
+        assertEquals("11 key auto 5 M0 rows", 3, params.mNumRows);
+        assertEquals("11 key auto 5 M0 left", 2, params.mLeftKeys);
+        assertEquals("11 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("11 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("11 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("11 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("11 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("11 key auto 5 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("11 key auto 5 M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("11 key auto 5 M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("11 key auto 5 M0 [8]", -1, params.getColumnPos(7));
+        assertEquals("11 key auto 5 M0 [9]", 2, params.getColumnPos(8));
+        assertEquals("11 key auto 5 M0 [A]", -2, params.getColumnPos(9));
+        assertEquals("11 key auto 5 M0 [B]", 0, params.getColumnPos(10));
+        assertEquals("11 key auto 5 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("11 key auto 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //       [B] [C]
+    // [A] [8] [6] [7] [9]
+    // [5] [3] <1> [2] [4]
+    public void testLayout12KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(12, 5, XPOS_M0);
+        assertEquals("12 key auto 5 M0 columns", 5, params.mNumColumns);
+        assertEquals("12 key auto 5 M0 rows", 3, params.mNumRows);
+        assertEquals("12 key auto 5 M0 left", 2, params.mLeftKeys);
+        assertEquals("12 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("12 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("12 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("12 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("12 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("12 key auto 5 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("12 key auto 5 M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("12 key auto 5 M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("12 key auto 5 M0 [8]", -1, params.getColumnPos(7));
+        assertEquals("12 key auto 5 M0 [9]", 2, params.getColumnPos(8));
+        assertEquals("12 key auto 5 M0 [A]", -2, params.getColumnPos(9));
+        assertEquals("12 key auto 5 M0 [B]", 0, params.getColumnPos(10));
+        assertEquals("12 key auto 5 M0 [C]", 1, params.getColumnPos(11));
+        assertEquals("12 key auto 5 M0 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("12 key auto 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //     [D] [B] [C]
+    // [A] [8] [6] [7] [9]
+    // [5] [3] <1> [2] [4]
+    public void testLayout13KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(13, 5, XPOS_M0);
+        assertEquals("13 key auto 5 M0 columns", 5, params.mNumColumns);
+        assertEquals("13 key auto 5 M0 rows", 3, params.mNumRows);
+        assertEquals("13 key auto 5 M0 left", 2, params.mLeftKeys);
+        assertEquals("13 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("13 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("13 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("13 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("13 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("13 key auto 5 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("13 key auto 5 M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("13 key auto 5 M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("13 key auto 5 M0 [8]", -1, params.getColumnPos(7));
+        assertEquals("13 key auto 5 M0 [9]", 2, params.getColumnPos(8));
+        assertEquals("13 key auto 5 M0 [A]", -2, params.getColumnPos(9));
+        assertEquals("13 key auto 5 M0 [B]", 0, params.getColumnPos(10));
+        assertEquals("13 key auto 5 M0 [C]", 1, params.getColumnPos(11));
+        assertEquals("13 key auto 5 M0 [D]", -1, params.getColumnPos(12));
+        assertEquals("13 key auto 5 M0 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("13 key auto 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //   [D] [B] [C] [E]
+    // [A] [8] [6] [7] [9]
+    // [5] [3] <1> [2] [4]
+    public void testLayout14KeyAuto5M0() {
+        MoreKeysKeyboardParams params = createParams(14, 5, XPOS_M0);
+        assertEquals("13 key auto 5 M0 columns", 5, params.mNumColumns);
+        assertEquals("13 key auto 5 M0 rows", 3, params.mNumRows);
+        assertEquals("13 key auto 5 M0 left", 2, params.mLeftKeys);
+        assertEquals("13 key auto 5 M0 right", 3, params.mRightKeys);
+        assertEquals("13 key auto 5 M0 <1>", 0, params.getColumnPos(0));
+        assertEquals("13 key auto 5 M0 [2]", 1, params.getColumnPos(1));
+        assertEquals("13 key auto 5 M0 [3]", -1, params.getColumnPos(2));
+        assertEquals("13 key auto 5 M0 [4]", 2, params.getColumnPos(3));
+        assertEquals("13 key auto 5 M0 [5]", -2, params.getColumnPos(4));
+        assertEquals("13 key auto 5 M0 [6]", 0, params.getColumnPos(5));
+        assertEquals("13 key auto 5 M0 [7]", 1, params.getColumnPos(6));
+        assertEquals("13 key auto 5 M0 [8]", -1, params.getColumnPos(7));
+        assertEquals("13 key auto 5 M0 [9]", 2, params.getColumnPos(8));
+        assertEquals("13 key auto 5 M0 [A]", -2, params.getColumnPos(9));
+        assertEquals("13 key auto 5 M0 [B]", 0, params.getColumnPos(10));
+        assertEquals("13 key auto 5 M0 [C]", 1, params.getColumnPos(11));
+        assertEquals("13 key auto 5 M0 [D]", -1, params.getColumnPos(12));
+        assertEquals("13 key auto 5 M0 [E]", 2, params.getColumnPos(13));
+        assertEquals("13 key auto 5 M0 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("13 key auto 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX());
+    }
+
+    //                     [J] [I] [H] ___|
+    // [G] [F] [E] [D] [C] [B] [A] [9] ___|
+    // [8] [7] [6] [5] [4] [3] [2] <1> ___|
+    public void testLayout19KeyAuto8R1() {
+        MoreKeysKeyboardParams params = createParams(19, 8, XPOS_R1);
+        assertEquals("19 key auto 8 R1 columns", 8, params.mNumColumns);
+        assertEquals("19 key auto 8 R1 rows", 3, params.mNumRows);
+        assertEquals("19 key auto 8 R1 left", 7, params.mLeftKeys);
+        assertEquals("19 key auto 8 R1 right", 1, params.mRightKeys);
+        assertEquals("19 key auto 8 R1 <1>", 0, params.getColumnPos(0));
+        assertEquals("19 key auto 8 R1 [2]", -1, params.getColumnPos(1));
+        assertEquals("19 key auto 8 R1 [3]", -2, params.getColumnPos(2));
+        assertEquals("19 key auto 8 R1 [4]", -3, params.getColumnPos(3));
+        assertEquals("19 key auto 8 R1 [5]", -4, params.getColumnPos(4));
+        assertEquals("19 key auto 8 R1 [6]", -5, params.getColumnPos(5));
+        assertEquals("19 key auto 8 R1 [7]", -6, params.getColumnPos(6));
+        assertEquals("19 key auto 8 R1 [8]", -7, params.getColumnPos(7));
+        assertEquals("19 key auto 8 R1 [9]", 0, params.getColumnPos(8));
+        assertEquals("19 key auto 8 R1 [A]", -1, params.getColumnPos(9));
+        assertEquals("19 key auto 8 R1 [B]", -2, params.getColumnPos(10));
+        assertEquals("19 key auto 8 R1 [C]", -3, params.getColumnPos(11));
+        assertEquals("19 key auto 8 R1 [D]", -4, params.getColumnPos(12));
+        assertEquals("19 key auto 8 R1 [E]", -5, params.getColumnPos(13));
+        assertEquals("19 key auto 8 R1 [F]", -6, params.getColumnPos(14));
+        assertEquals("19 key auto 8 R1 [G]", -7, params.getColumnPos(15));
+        assertEquals("19 key auto 8 R1 [H]", 0, params.getColumnPos(16));
+        assertEquals("19 key auto 8 R1 [I]", -1, params.getColumnPos(17));
+        assertEquals("19 key auto 8 R1 [J]", -2, params.getColumnPos(18));
+        assertEquals("19 key auto 8 R1 adjust", 0, params.mTopRowAdjustment);
+        assertEquals("19 key auto 8 R1 default", WIDTH * 7, params.getDefaultKeyCoordX());
+    }
+
+    //                   [J] [H] [I]   ___|
+    // [G] [F] [E] [D] [C] [B] [9] [A] ___|
+    // [8] [7] [6] [5] [4] [3] <1> [2] ___|
+    public void testLayout19KeyAuto8R2() {
+        MoreKeysKeyboardParams params = createParams(19, 8, XPOS_R2);
+        assertEquals("19 key auto 8 R2 columns", 8, params.mNumColumns);
+        assertEquals("19 key auto 8 R2 rows", 3, params.mNumRows);
+        assertEquals("19 key auto 8 R2 left", 6, params.mLeftKeys);
+        assertEquals("19 key auto 8 R2 right", 2, params.mRightKeys);
+        assertEquals("19 key auto 8 R2 <1>", 0, params.getColumnPos(0));
+        assertEquals("19 key auto 8 R2 [2]", 1, params.getColumnPos(1));
+        assertEquals("19 key auto 8 R2 [3]", -1, params.getColumnPos(2));
+        assertEquals("19 key auto 8 R2 [4]", -2, params.getColumnPos(3));
+        assertEquals("19 key auto 8 R2 [5]", -3, params.getColumnPos(4));
+        assertEquals("19 key auto 8 R2 [6]", -4, params.getColumnPos(5));
+        assertEquals("19 key auto 8 R2 [7]", -5, params.getColumnPos(6));
+        assertEquals("19 key auto 8 R2 [8]", -6, params.getColumnPos(7));
+        assertEquals("19 key auto 8 R2 [9]", 0, params.getColumnPos(8));
+        assertEquals("19 key auto 8 R2 [A]", 1, params.getColumnPos(9));
+        assertEquals("19 key auto 8 R2 [B]", -1, params.getColumnPos(10));
+        assertEquals("19 key auto 8 R2 [C]", -2, params.getColumnPos(11));
+        assertEquals("19 key auto 8 R2 [D]", -3, params.getColumnPos(12));
+        assertEquals("19 key auto 8 R2 [E]", -4, params.getColumnPos(13));
+        assertEquals("19 key auto 8 R2 [F]", -5, params.getColumnPos(14));
+        assertEquals("19 key auto 8 R2 [G]", -6, params.getColumnPos(15));
+        assertEquals("19 key auto 8 R2 [H]", 0, params.getColumnPos(16));
+        assertEquals("19 key auto 8 R2 [I]", 1, params.getColumnPos(17));
+        assertEquals("19 key auto 8 R2 [J]", -1, params.getColumnPos(18));
+        assertEquals("19 key auto 8 R2 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("19 key auto 8 R2 default", WIDTH * 6, params.getDefaultKeyCoordX());
+    }
+
+    //               [J] [H] [I]       ___|
+    // [G] [F] [E] [D] [B] [9] [A] [C] ___|
+    // [8] [7] [6] [5] [3] <1> [2] [4] ___|
+    public void testLayout19KeyAuto8R3() {
+        MoreKeysKeyboardParams params = createParams(19, 8, XPOS_R3);
+        assertEquals("19 key auto 8 R3 columns", 8, params.mNumColumns);
+        assertEquals("19 key auto 8 R3 rows", 3, params.mNumRows);
+        assertEquals("19 key auto 8 R3 left", 5, params.mLeftKeys);
+        assertEquals("19 key auto 8 R3 right", 3, params.mRightKeys);
+        assertEquals("19 key auto 8 R3 <1>", 0, params.getColumnPos(0));
+        assertEquals("19 key auto 8 R3 [2]", 1, params.getColumnPos(1));
+        assertEquals("19 key auto 8 R3 [3]", -1, params.getColumnPos(2));
+        assertEquals("19 key auto 8 R3 [4]", 2, params.getColumnPos(3));
+        assertEquals("19 key auto 8 R3 [5]", -2, params.getColumnPos(4));
+        assertEquals("19 key auto 8 R3 [6]", -3, params.getColumnPos(5));
+        assertEquals("19 key auto 8 R3 [7]", -4, params.getColumnPos(6));
+        assertEquals("19 key auto 8 R3 [8]", -5, params.getColumnPos(7));
+        assertEquals("19 key auto 8 R3 [9]", 0, params.getColumnPos(8));
+        assertEquals("19 key auto 8 R3 [A]", 1, params.getColumnPos(9));
+        assertEquals("19 key auto 8 R3 [B]", -1, params.getColumnPos(10));
+        assertEquals("19 key auto 8 R3 [C]", 2, params.getColumnPos(11));
+        assertEquals("19 key auto 8 R3 [D]", -2, params.getColumnPos(12));
+        assertEquals("19 key auto 8 R3 [E]", -3, params.getColumnPos(13));
+        assertEquals("19 key auto 8 R3 [F]", -4, params.getColumnPos(14));
+        assertEquals("19 key auto 8 R3 [G]", -5, params.getColumnPos(15));
+        assertEquals("19 key auto 8 R3 [H]", 0, params.getColumnPos(16));
+        assertEquals("19 key auto 8 R3 [I]", 1, params.getColumnPos(17));
+        assertEquals("19 key auto 8 R3 [J]", -1, params.getColumnPos(18));
+        assertEquals("19 key auto 8 R3 adjust", -1, params.mTopRowAdjustment);
+        assertEquals("19 key auto 8 R3 default", WIDTH * 5, params.getDefaultKeyCoordX());
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java
index 6d9c3fd..7e51d95 100644
--- a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java
@@ -47,7 +47,8 @@
             final int coordXInParent) {
         final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams();
         params.setParameters(numKeys, columnNum, WIDTH, HEIGHT, coordXInParent, KEYBOARD_WIDTH,
-                true /* isFixedOrderColumn */, 0 /* dividerWidth */);
+                true /* isMoreKeysFixedColumn */, true /* isMoreKeysFixedOrder */,
+                0 /* dividerWidth */);
         return params;
     }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderMaxOrderTests.java
similarity index 99%
rename from tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java
rename to tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderMaxOrderTests.java
index b213721..806790e 100644
--- a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderMaxOrderTests.java
@@ -22,7 +22,7 @@
 import com.android.inputmethod.keyboard.MoreKeysKeyboard.MoreKeysKeyboardParams;
 
 @MediumTest
-public class MoreKeysKeyboardBuilderTests extends AndroidTestCase {
+public class MoreKeysKeyboardBuilderMaxOrderTests extends AndroidTestCase {
     private static final int WIDTH = 10;
     private static final int HEIGHT = 10;
 
@@ -47,7 +47,8 @@
             final int coordXInParent) {
         final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams();
         params.setParameters(numKeys, maxColumns, WIDTH, HEIGHT, coordXInParent, KEYBOARD_WIDTH,
-                false /* isFixedOrderColumn */, 0 /* dividerWidth */);
+                false /* isMoreKeysFixedColumn */, false /* isMoreKeysFixedOrder */,
+                0 /* dividerWidth */);
         return params;
     }
 
diff --git a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
index c28d08c..869c550 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
@@ -148,5 +148,15 @@
 
         // Make sure getTypedWordInfoOrNull() returns null.
         assertNull(SuggestedWords.EMPTY.getTypedWordInfoOrNull());
+
+        final SuggestedWords emptySuggestedWords = new SuggestedWords(
+                new ArrayList<SuggestedWordInfo>(), null /* rawSuggestions */,
+                false /* typedWordValid */,
+                false /* willAutoCorrect */,
+                false /* isObsoleteSuggestions */,
+                SuggestedWords.INPUT_STYLE_NONE);
+        assertNull(emptySuggestedWords.getTypedWordInfoOrNull());
+
+        assertNull(SuggestedWords.EMPTY.getTypedWordInfoOrNull());
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
index b656292..e9a97ff 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
@@ -52,7 +52,7 @@
         final ArrayList<String> dictTypes = new ArrayList<>();
         dictTypes.add(Dictionary.TYPE_MAIN);
         dictTypes.add(Dictionary.TYPE_PERSONALIZATION);
-        final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator();
+        final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator(getContext());
         dictionaryFacilitator.resetDictionariesForTesting(getContext(), LOCALE_EN_US, dictTypes,
                 new HashMap<String, File>(), new HashMap<String, Map<String, String>>());
         return dictionaryFacilitator;