AOSP changes to use KeyboardLayout to support the new DictionaryFacilitator

Change-Id: Ie0c9ce805d9ad009fc9bbaac37b715aff90cd844
diff --git a/common/src/com/android/inputmethod/latin/common/Constants.java b/common/src/com/android/inputmethod/latin/common/Constants.java
index a860d35..2095d2e 100644
--- a/common/src/com/android/inputmethod/latin/common/Constants.java
+++ b/common/src/com/android/inputmethod/latin/common/Constants.java
@@ -175,10 +175,12 @@
     public static final int MAX_CHARACTERS_FOR_RECAPITALIZATION = 1024 * 100;
 
     // Must be equal to MAX_WORD_LENGTH in native/jni/src/defines.h
+    // TODO: create a overlay and update the value appropriately for the new decoder.
     public static final int DICTIONARY_MAX_WORD_LENGTH = 48;
 
     // (MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1)-gram is supported in Java side. Needs to modify
     // MAX_PREV_WORD_COUNT_FOR_N_GRAM in native/jni/src/defines.h for suggestions.
+    // TODO: create a overlay and update the value appropriately for the new decoder.
     public static final int MAX_PREV_WORD_COUNT_FOR_N_GRAM = 3;
 
     // Key events coming any faster than this are long-presses.
@@ -330,6 +332,10 @@
      */
     public static final int DEFAULT_GESTURE_POINTS_CAPACITY = 128;
 
+    public static final int MAX_IME_DECODER_RESULTS = 20;
+    public static final int DECODER_SCORE_SCALAR = 1000000;
+    public static final int DECODER_MAX_SCORE = 1000000000;
+
     private Constants() {
         // This utility class is not publicly instantiable.
     }
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index 460c1e4..48cca76 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -21,6 +21,7 @@
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.keyboard.KeyboardLayout;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
 import com.android.inputmethod.latin.utils.SuggestionResults;
 
@@ -131,7 +132,8 @@
     // TODO: Revise the way to fusion suggestion results.
     SuggestionResults getSuggestionResults(final WordComposer composer,
             final NgramContext ngramContext, final long proximityInfoHandle,
-            final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId);
+            final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId,
+            final int inputStyle, final KeyboardLayout keyboardLayout);
 
     boolean isValidWord(final String word, final boolean ignoreCase);
 
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
index ee4a7ea..99f0247 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
@@ -23,6 +23,7 @@
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.keyboard.KeyboardLayout;
 import com.android.inputmethod.latin.NgramContext.WordInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.common.Constants;
@@ -699,9 +700,11 @@
     }
 
     // TODO: Revise the way to fusion suggestion results.
-    public SuggestionResults getSuggestionResults(final WordComposer composer,
-            final NgramContext ngramContext, final long proximityInfoHandle,
-            final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId) {
+    @Override
+    public SuggestionResults getSuggestionResults(WordComposer composer,
+            NgramContext ngramContext, long proximityInfoHandle,
+            SettingsValuesForSuggestion settingsValuesForSuggestion, int sessionId,
+            int inputStyle, KeyboardLayout keyboardLayout) {
         final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
         final SuggestionResults suggestionResults = new SuggestionResults(
                 SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext());
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 8227008..9a1df49 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1520,7 +1520,8 @@
             return;
         }
         mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard.getProximityInfo(),
-                mKeyboardSwitcher.getKeyboardShiftMode(), inputStyle, sequenceNumber, callback);
+                mKeyboardSwitcher.getKeyboardShiftMode(), inputStyle, sequenceNumber, callback,
+                keyboard.getKeyboardLayout());
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/NgramContext.java b/java/src/com/android/inputmethod/latin/NgramContext.java
index b477312..2d66fb0 100644
--- a/java/src/com/android/inputmethod/latin/NgramContext.java
+++ b/java/src/com/android/inputmethod/latin/NgramContext.java
@@ -22,6 +22,7 @@
 import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.common.StringUtils;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 
 import javax.annotation.Nonnull;
@@ -38,6 +39,10 @@
     public static final NgramContext BEGINNING_OF_SENTENCE =
             new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
 
+    public static final String BEGINNING_OF_SENTENCE_TAG = "<S>";
+
+    public static final String CONTEXT_SEPARATOR = " ";
+
     /**
      * Word information used to represent previous words information.
      */
@@ -114,6 +119,31 @@
         return new NgramContext(prevWordsInfo);
     }
 
+
+    /**
+     * Extracts the previous words context.
+     *
+     * @return a String with the previous words separated by white space.
+     */
+    public String extractPrevWordsContext() {
+        final ArrayList<String> terms = new ArrayList<>();
+        for (int i = mPrevWordsInfo.length - 1; i >= 0; --i) {
+            if (mPrevWordsInfo[i] != null && mPrevWordsInfo[i].isValid()) {
+                final NgramContext.WordInfo wordInfo = mPrevWordsInfo[i];
+                if (wordInfo.mIsBeginningOfSentence) {
+                    terms.add(BEGINNING_OF_SENTENCE_TAG);
+                } else {
+                    final String term = wordInfo.mWord.toString();
+                    if (!term.isEmpty()) {
+                        terms.add(term);
+                    }
+                }
+            }
+        }
+        return terms.size() == 0 ? BEGINNING_OF_SENTENCE_TAG
+                : TextUtils.join(CONTEXT_SEPARATOR, terms);
+    }
+
     public boolean isValid() {
         return mPrevWordsCount > 0 && mPrevWordsInfo[0].isValid();
     }
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 0bf0f68..ddb2b53 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -18,6 +18,7 @@
 
 import android.text.TextUtils;
 
+import com.android.inputmethod.keyboard.KeyboardLayout;
 import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.common.Constants;
@@ -97,14 +98,16 @@
             final NgramContext ngramContext, final ProximityInfo proximityInfo,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
             final boolean isCorrectionEnabled, final int inputStyle, final int sequenceNumber,
-            final OnGetSuggestedWordsCallback callback) {
+            final OnGetSuggestedWordsCallback callback,
+            final KeyboardLayout keyboardLayout) {
         if (wordComposer.isBatchMode()) {
             getSuggestedWordsForBatchInput(wordComposer, ngramContext, proximityInfo,
-                    settingsValuesForSuggestion, inputStyle, sequenceNumber, callback);
+                    settingsValuesForSuggestion, inputStyle, sequenceNumber, callback,
+                    keyboardLayout);
         } else {
             getSuggestedWordsForNonBatchInput(wordComposer, ngramContext, proximityInfo,
                     settingsValuesForSuggestion, inputStyle, isCorrectionEnabled,
-                    sequenceNumber, callback);
+                    sequenceNumber, callback, keyboardLayout);
         }
     }
 
@@ -163,7 +166,8 @@
             final NgramContext ngramContext, final ProximityInfo proximityInfo,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
             final int inputStyleIfNotPrediction, final boolean isCorrectionEnabled,
-            final int sequenceNumber, final OnGetSuggestedWordsCallback callback) {
+            final int sequenceNumber, final OnGetSuggestedWordsCallback callback,
+            final KeyboardLayout keyboardLayout) {
         final String typedWordString = wordComposer.getTypedWord();
         final int trailingSingleQuotesCount =
                 StringUtils.getTrailingSingleQuotesCount(typedWordString);
@@ -173,7 +177,8 @@
 
         final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
                 wordComposer, ngramContext, proximityInfo.getNativeProximityInfo(),
-                settingsValuesForSuggestion, SESSION_ID_TYPING);
+                settingsValuesForSuggestion, SESSION_ID_TYPING, inputStyleIfNotPrediction,
+                keyboardLayout);
         final Locale mostProbableLocale = mDictionaryFacilitator.getMostProbableLocale();
         final ArrayList<SuggestedWordInfo> suggestionsContainer =
                 getTransformedSuggestedWordInfoList(wordComposer, suggestionResults,
@@ -270,7 +275,9 @@
             hasAutoCorrection = false;
         } else {
             final SuggestedWordInfo firstSuggestion = suggestionResults.first();
-            if (!AutoCorrectionUtils.suggestionExceedsThreshold(
+            if (suggestionResults.mAutocorrectRecommendation) {
+                hasAutoCorrection = true;
+            } else if (!AutoCorrectionUtils.suggestionExceedsThreshold(
                     firstSuggestion, consideredWord, mAutoCorrectionThreshold)) {
                 // Score is too low for autocorrect
                 hasAutoCorrection = false;
@@ -339,10 +346,11 @@
             final NgramContext ngramContext, final ProximityInfo proximityInfo,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
             final int inputStyle, final int sequenceNumber,
-            final OnGetSuggestedWordsCallback callback) {
+            final OnGetSuggestedWordsCallback callback,
+            final KeyboardLayout keyboardLayout) {
         final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
                 wordComposer, ngramContext, proximityInfo.getNativeProximityInfo(),
-                settingsValuesForSuggestion, SESSION_ID_GESTURE);
+                settingsValuesForSuggestion, SESSION_ID_GESTURE, inputStyle, keyboardLayout);
         // For transforming words that don't come from a dictionary, because it's our best bet
         final Locale defaultLocale = mDictionaryFacilitator.getMostProbableLocale();
         final ArrayList<SuggestedWordInfo> suggestionsContainer =
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index e80e362..e6f2f1e 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.latin;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.event.CombinerChain;
 import com.android.inputmethod.event.Event;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
@@ -464,4 +465,14 @@
     public String getRejectedBatchModeSuggestion() {
         return mRejectedBatchModeSuggestion;
     }
+
+    @UsedForTesting
+    void addInputPointerForTest(int index, int keyX, int keyY) {
+        mInputPointers.addPointerAt(index, keyX, keyY, 0, 0);
+    }
+
+    @UsedForTesting
+    void setTypedWordCacheForTests(String typedWordCacheForTests) {
+        mTypedWordCache = typedWordCacheForTests;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 18927ce..12c384d 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -32,6 +32,7 @@
 import com.android.inputmethod.compat.SuggestionSpanUtils;
 import com.android.inputmethod.event.Event;
 import com.android.inputmethod.event.InputTransaction;
+import com.android.inputmethod.keyboard.KeyboardLayout;
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
 import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.Dictionary;
@@ -2115,7 +2116,8 @@
 
     public void getSuggestedWords(final SettingsValues settingsValues,
             final ProximityInfo proximityInfo, final int keyboardShiftMode, final int inputStyle,
-            final int sequenceNumber, final OnGetSuggestedWordsCallback callback) {
+            final int sequenceNumber, final OnGetSuggestedWordsCallback callback,
+            final KeyboardLayout keyboardLayout) {
         mWordComposer.adviseCapitalizedModeBeforeFetchingSuggestions(
                 getActualCapsMode(settingsValues, keyboardShiftMode));
         mSuggest.getSuggestedWords(mWordComposer,
@@ -2129,7 +2131,7 @@
                 new SettingsValuesForSuggestion(settingsValues.mBlockPotentiallyOffensive,
                         settingsValues.mPhraseGestureEnabled),
                 settingsValues.mAutoCorrectionEnabledPerUserSettings,
-                inputStyle, sequenceNumber, callback);
+                inputStyle, sequenceNumber, callback, keyboardLayout);
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 8744020..7851dd2 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -27,6 +27,7 @@
 
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.KeyboardLayout;
 import com.android.inputmethod.keyboard.KeyboardLayoutSet;
 import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.DictionaryFacilitator;
@@ -34,6 +35,7 @@
 import com.android.inputmethod.latin.NgramContext;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
 import com.android.inputmethod.latin.utils.ScriptUtils;
@@ -159,7 +161,8 @@
     }
 
     public SuggestionResults getSuggestionResults(final Locale locale, final WordComposer composer,
-            final NgramContext ngramContext, final ProximityInfo proximityInfo) {
+            final NgramContext ngramContext, final ProximityInfo proximityInfo,
+            final KeyboardLayout keyboardLayout) {
         Integer sessionId = null;
         mSemaphore.acquireUninterruptibly();
         try {
@@ -168,7 +171,7 @@
                     mDictionaryFacilitatorCache.get(locale);
             return dictionaryFacilitatorForLocale.getSuggestionResults(composer, ngramContext,
                     proximityInfo.getNativeProximityInfo(), mSettingsValuesForSuggestion,
-                    sessionId);
+                    sessionId, SuggestedWords.INPUT_STYLE_TYPING, keyboardLayout);
         } finally {
             if (sessionId != null) {
                 mSessionIdPool.add(sessionId);
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index 832bfd0..0b5e12f 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -29,6 +29,7 @@
 
 import com.android.inputmethod.compat.SuggestionsInfoCompatUtils;
 import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardLayout;
 import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.NgramContext;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
@@ -271,18 +272,21 @@
             final int[] codePoints = StringUtils.toCodePointArray(text);
             final int[] coordinates;
             final ProximityInfo proximityInfo;
+            final KeyboardLayout keyboardLayout;
             if (null == keyboard) {
                 coordinates = CoordinateUtils.newCoordinateArray(codePoints.length,
                         Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
                 proximityInfo = null;
+                keyboardLayout = null;
             } else {
                 coordinates = keyboard.getCoordinates(codePoints);
                 proximityInfo = keyboard.getProximityInfo();
+                keyboardLayout = keyboard.getKeyboardLayout();
             }
             composer.setComposingWord(codePoints, coordinates);
             // TODO: Don't gather suggestions if the limit is <= 0 unless necessary
             final SuggestionResults suggestionResults = mService.getSuggestionResults(
-                    mLocale, composer, ngramContext, proximityInfo);
+                    mLocale, composer, ngramContext, proximityInfo, keyboardLayout);
             final Result result = getResult(capitalizeType, mLocale, suggestionsLimit,
                     mService.getRecommendedThreshold(), text, suggestionResults);
             isInDict = isInDictForAnyCapitalization(text, capitalizeType);
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java
index 56a04a8..af99797 100644
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java
@@ -38,6 +38,7 @@
 import com.android.inputmethod.latin.DictionaryFacilitatorLruCache;
 import com.android.inputmethod.latin.NgramContext;
 import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.WordComposer;
 import com.android.inputmethod.latin.common.StringUtils;
@@ -252,7 +253,9 @@
             suggestionResults = dictionaryFacilitator.getSuggestionResults(composer,
                     NgramContext.EMPTY_PREV_WORDS_INFO,
                     keyboard.getProximityInfo().getNativeProximityInfo(),
-                    settingsValuesForSuggestion, 0 /* sessionId */);
+                    settingsValuesForSuggestion, 0 /* sessionId */,
+                    SuggestedWords.INPUT_STYLE_TYPING,
+                    keyboard.getKeyboardLayout());
         }
         if (suggestionResults.isEmpty()) {
             return false;
diff --git a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
index b319aeb..10e3994 100644
--- a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
+++ b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
@@ -33,14 +33,21 @@
     // TODO: Instead of a boolean , we may want to include the context of this suggestion results,
     // such as {@link NgramContext}.
     public final boolean mIsBeginningOfSentence;
+    public final boolean mAutocorrectRecommendation;
     private final int mCapacity;
 
     public SuggestionResults(final int capacity, final boolean isBeginningOfSentence) {
-        this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence);
+        this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence, false);
     }
 
-    private SuggestionResults(final Comparator<SuggestedWordInfo> comparator,
-            final int capacity, final boolean isBeginningOfSentence) {
+    public SuggestionResults(final int capacity, final boolean isBeginningOfSentence,
+            final boolean autocorrectRecommendation) {
+        this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence,
+                autocorrectRecommendation);
+    }
+
+    private SuggestionResults(final Comparator<SuggestedWordInfo> comparator, final int capacity,
+            final boolean isBeginningOfSentence, final boolean autocorrectRecommendation) {
         super(comparator);
         mCapacity = capacity;
         if (ProductionFlags.INCLUDE_RAW_SUGGESTIONS) {
@@ -49,6 +56,7 @@
             mRawSuggestions = null;
         }
         mIsBeginningOfSentence = isBeginningOfSentence;
+        mAutocorrectRecommendation = autocorrectRecommendation;
     }
 
     @Override
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutTest.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutTest.java
index 9aced5c..733bf96 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutTest.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutTest.java
@@ -45,8 +45,10 @@
         assertEquals(0, keyboardLayout.getKeyXCoordinates().length);
         assertEquals(0, keyboardLayout.getKeyYCoordinates().length);
 
-        Key key1 = new Key("label1", 101, 102, "101", "101hint", 103, 104, 105, 106, 1100, 1101, 2, 2);
-        Key key2 = new Key("label2", 201, 202, "201", "201hint", 203, 204, 205, 206, 2100, 2201, 2, 2);
+        Key key1 = new Key("label1", 101, 102, "101", "101hint", 103, 104, 105, 106, 1100, 1101,
+                10, 10);
+        Key key2 = new Key("label2", 201, 103, "201", "201hint", 203, 204, 205, 206, 2100, 2101,
+                10, 10);
 
         ArrayList<Key> sortedKeys = new ArrayList<>(2);
         sortedKeys.add(key1);
@@ -57,5 +59,23 @@
         assertEquals(2, keyboardLayout.getKeyHeights().length);
         assertEquals(2, keyboardLayout.getKeyXCoordinates().length);
         assertEquals(2, keyboardLayout.getKeyYCoordinates().length);
+
+        assertEquals(102, keyboardLayout.getKeyCodes()[0]);
+        // xCo + horizontalGap/2
+        assertEquals(105 + 5, keyboardLayout.getKeyXCoordinates()[0]);
+        assertEquals(106, keyboardLayout.getKeyYCoordinates()[0]);
+        // width - horizontalGap
+        assertEquals(1100 - 10, keyboardLayout.getKeyWidths()[0]);
+        // height - verticalGap
+        assertEquals(1101 - 10, keyboardLayout.getKeyHeights()[0]);
+
+        assertEquals(103, keyboardLayout.getKeyCodes()[1]);
+        // xCo + horizontalGap/2
+        assertEquals(205 + 5, keyboardLayout.getKeyXCoordinates()[1]);
+        assertEquals(206, keyboardLayout.getKeyYCoordinates()[1]);
+        // width - horizontalGap
+        assertEquals(2100 - 10, keyboardLayout.getKeyWidths()[1]);
+        // height - verticalGap
+        assertEquals(2101 - 10, keyboardLayout.getKeyHeights()[1]);
     }
 }