Merge "Use unique_ptr."
diff --git a/java/res/xml-sw600dp/key_azerty3_right.xml b/java/res/xml-sw600dp/key_azerty3_right.xml
deleted file mode 100644
index 25b0e52..0000000
--- a/java/res/xml-sw600dp/key_azerty3_right.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
-    <Key
-        latin:keySpec=":"
-        latin:keyHintLabel=";"
-        latin:moreKeys=";"
-        latin:keyStyle="hasShiftedLetterHintStyle" />
-</merge>
diff --git a/java/res/xml/key_azerty3_right.xml b/java/res/xml/key_azerty3_right.xml
deleted file mode 100644
index 85a0666..0000000
--- a/java/res/xml/key_azerty3_right.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
-    <switch>
-        <case
-            latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
-        >
-            <Key
-                latin:keySpec="\?" />
-        </case>
-        <default>
-            <Key
-                latin:keySpec="\'"
-                latin:moreKeys="!text/more_keys_for_single_quote" />
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/rowkeys_azerty3.xml b/java/res/xml/rowkeys_azerty3.xml
index 0aa2153..c955e23 100644
--- a/java/res/xml/rowkeys_azerty3.xml
+++ b/java/res/xml/rowkeys_azerty3.xml
@@ -37,6 +37,17 @@
     <Key
         latin:keySpec="n"
         latin:moreKeys="!text/more_keys_for_n" />
-    <include
-        latin:keyboardLayout="@xml/key_azerty3_right" />
+    <switch>
+        <case
+            latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+        >
+            <Key
+                latin:keySpec="\?" />
+        </case>
+        <default>
+            <Key
+                latin:keySpec="\'"
+                latin:moreKeys="!text/more_keys_for_single_quote" />
+        </default>
+    </switch>
 </merge>
diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java
index e7932b5..b9d526b 100644
--- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java
@@ -507,4 +507,44 @@
         return codePointCount(casedText) == 1
                 ? casedText.codePointAt(0) : CODE_UNSPECIFIED;
     }
+
+    @UsedForTesting
+    public static class Stringizer<E> {
+        public String stringize(final E element) {
+            return element != null ? element.toString() : "null";
+        }
+
+        @UsedForTesting
+        public final String join(final E[] array) {
+            return joinStringArray(toStringArray(array), null /* delimiter */);
+        }
+
+        @UsedForTesting
+        public final String join(final E[] array, final String delimiter) {
+            return joinStringArray(toStringArray(array), delimiter);
+        }
+
+        protected String[] toStringArray(final E[] array) {
+            final String[] stringArray = new String[array.length];
+            for (int index = 0; index < array.length; index++) {
+                stringArray[index] = stringize(array[index]);
+            }
+            return stringArray;
+        }
+
+        protected String joinStringArray(final String[] stringArray, final String delimiter) {
+            if (stringArray == null) {
+                return "null";
+            }
+            if (delimiter == null) {
+                return Arrays.toString(stringArray);
+            }
+            final StringBuilder sb = new StringBuilder();
+            for (int index = 0; index < stringArray.length; index++) {
+                sb.append(index == 0 ? "[" : delimiter);
+                sb.append(stringArray[index]);
+            }
+            return sb + "]";
+        }
+    }
 }
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 0715fbd..4c57af0 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -344,9 +344,6 @@
 #define MAX_POINTER_COUNT 1
 #define MAX_POINTER_COUNT_G 2
 
-template<typename T> AK_FORCE_INLINE const T &min(const T &a, const T &b) { return a < b ? a : b; }
-template<typename T> AK_FORCE_INLINE const T &max(const T &a, const T &b) { return a > b ? a : b; }
-
 // DEBUG
 #define INPUTLENGTH_FOR_DEBUG (-1)
 #define MIN_OUTPUT_INDEX_FOR_DEBUG (-1)
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
index 7461f0c..1f02731 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
@@ -17,6 +17,7 @@
 #ifndef LATINIME_DIC_NODE_PRIORITY_QUEUE_H
 #define LATINIME_DIC_NODE_PRIORITY_QUEUE_H
 
+#include <algorithm>
 #include <queue>
 #include <vector>
 
@@ -49,7 +50,7 @@
 
     AK_FORCE_INLINE void setMaxSize(const int maxSize) {
         ASSERT(maxSize <= mCapacity);
-        mMaxSize = min(maxSize, mCapacity);
+        mMaxSize = std::min(maxSize, mCapacity);
     }
 
     AK_FORCE_INLINE void clearAndResizeToCapacity() {
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
index 71bcab6..a6ea68c 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
@@ -16,6 +16,7 @@
 
 #include "suggest/core/dicnode/dic_node_utils.h"
 
+#include <algorithm>
 #include <cstring>
 
 #include "suggest/core/dicnode/dic_node.h"
@@ -117,7 +118,7 @@
         }
         actualLength0 = i + 1;
     }
-    actualLength0 = min(actualLength0, MAX_WORD_LENGTH);
+    actualLength0 = std::min(actualLength0, MAX_WORD_LENGTH);
     memmove(dest, src0, actualLength0 * sizeof(dest[0]));
     if (!src1 || length1 == 0) {
         return actualLength0;
@@ -129,7 +130,7 @@
         }
         actualLength1 = i + 1;
     }
-    actualLength1 = min(actualLength1, MAX_WORD_LENGTH - actualLength0);
+    actualLength1 = std::min(actualLength1, MAX_WORD_LENGTH - actualLength0);
     memmove(&dest[actualLength0], src1, actualLength1 * sizeof(dest[0]));
     return actualLength0 + actualLength1;
 }
diff --git a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
index 8493b6a..c31c056 100644
--- a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
+++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
@@ -17,6 +17,7 @@
 #ifndef LATINIME_DIC_NODES_CACHE_H
 #define LATINIME_DIC_NODES_CACHE_H
 
+#include <algorithm>
 #include <stdint.h>
 
 #include "defines.h"
@@ -51,7 +52,7 @@
         // We want to use the max capacity for the current active dic node queue.
         mActiveDicNodes->clearAndResizeToCapacity();
         // nextActiveSize is used to limit the next iteration's active dic node size.
-        const int nextActiveSizeFittingToTheCapacity = min(nextActiveSize, getCacheCapacity());
+        const int nextActiveSizeFittingToTheCapacity = std::min(nextActiveSize, getCacheCapacity());
         mNextActiveDicNodes->clearAndResize(nextActiveSizeFittingToTheCapacity);
         mTerminalDicNodes->clearAndResize(terminalSize);
         // We want to use the max capacity for the cached dic nodes that will be used for the
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h
index fc68510..abafc0e 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h
@@ -17,6 +17,7 @@
 #ifndef LATINIME_DIC_NODE_STATE_OUTPUT_H
 #define LATINIME_DIC_NODE_STATE_OUTPUT_H
 
+#include <algorithm>
 #include <cstring> // for memmove()
 #include <stdint.h>
 
@@ -49,7 +50,8 @@
     void addMergedNodeCodePoints(const uint16_t mergedNodeCodePointCount,
             const int *const mergedNodeCodePoints) {
         if (mergedNodeCodePoints) {
-            const int additionalCodePointCount = min(static_cast<int>(mergedNodeCodePointCount),
+            const int additionalCodePointCount = std::min(
+                    static_cast<int>(mergedNodeCodePointCount),
                     MAX_WORD_LENGTH - mOutputtedCodePointCount);
             memmove(&mCodePointsBuf[mOutputtedCodePointCount], mergedNodeCodePoints,
                     additionalCodePointCount * sizeof(mCodePointsBuf[0]));
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h
index e7108d9..7868f78 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h
@@ -17,6 +17,7 @@
 #ifndef LATINIME_DIC_NODE_STATE_PREVWORD_H
 #define LATINIME_DIC_NODE_STATE_PREVWORD_H
 
+#include <algorithm>
 #include <cstring> // for memset() and memmove()
 #include <stdint.h>
 
@@ -69,7 +70,7 @@
             const int prevWordNodePos, const int *const src0, const int16_t length0,
             const int *const src1, const int16_t length1,
             const int prevWordSecondWordFirstInputIndex, const int lastInputIndex) {
-        mPrevWordCount = min(prevWordCount, static_cast<int16_t>(MAX_RESULTS));
+        mPrevWordCount = std::min(prevWordCount, static_cast<int16_t>(MAX_RESULTS));
         mPrevWordProbability = prevWordProbability;
         mPrevWordPtNodePos = prevWordNodePos;
         int twoWordsLen =
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
index 11c201e..18b7d73 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
@@ -17,6 +17,7 @@
 #ifndef LATINIME_DIC_NODE_STATE_SCORING_H
 #define LATINIME_DIC_NODE_STATE_SCORING_H
 
+#include <algorithm>
 #include <stdint.h>
 
 #include "defines.h"
@@ -199,7 +200,7 @@
             mNormalizedCompoundDistance = mSpatialDistance + mLanguageDistance;
         } else {
             mNormalizedCompoundDistance = (mSpatialDistance + mLanguageDistance)
-                    / static_cast<float>(max(1, totalInputIndex));
+                    / static_cast<float>(std::max(1, totalInputIndex));
         }
     }
 };
diff --git a/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp b/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp
index d0b96b0..0859df4 100644
--- a/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-#include <cstring>
-
 #define LOG_TAG "LatinIME: bigram_dictionary.cpp"
 
 #include "bigram_dictionary.h"
 
+#include <algorithm>
+#include <cstring>
+
 #include "defines.h"
 #include "suggest/core/dictionary/binary_dictionary_bigrams_iterator.h"
 #include "suggest/core/dictionary/dictionary.h"
@@ -142,7 +143,7 @@
                 outBigramCodePoints, outputTypes);
         ++bigramCount;
     }
-    return min(bigramCount, MAX_RESULTS);
+    return std::min(bigramCount, MAX_RESULTS);
 }
 
 // Returns a pointer to the start of the bigram list.
diff --git a/native/jni/src/suggest/core/layout/proximity_info.cpp b/native/jni/src/suggest/core/layout/proximity_info.cpp
index ee8e59e..8b3ae4d 100644
--- a/native/jni/src/suggest/core/layout/proximity_info.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info.cpp
@@ -18,6 +18,7 @@
 
 #include "suggest/core/layout/proximity_info.h"
 
+#include <algorithm>
 #include <cstring>
 #include <cmath>
 
@@ -63,7 +64,7 @@
                           static_cast<float>(mostCommonKeyWidth))),
           CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth),
           CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight),
-          KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)),
+          KEY_COUNT(std::min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)),
           KEYBOARD_WIDTH(keyboardWidth), KEYBOARD_HEIGHT(keyboardHeight),
           KEYBOARD_HYPOTENUSE(hypotf(KEYBOARD_WIDTH, KEYBOARD_HEIGHT)),
           HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates
diff --git a/native/jni/src/suggest/core/layout/proximity_info_state.cpp b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
index 40c3448..2919904 100644
--- a/native/jni/src/suggest/core/layout/proximity_info_state.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
@@ -18,6 +18,7 @@
 
 #include "suggest/core/layout/proximity_info_state.h"
 
+#include <algorithm>
 #include <cstring> // for memset() and memmove()
 #include <sstream> // for debug prints
 #include <vector>
@@ -171,7 +172,7 @@
     const int keyId = mProximityInfo->getKeyIndexOf(codePoint);
     if (keyId != NOT_AN_INDEX) {
         const int index = inputIndex * mProximityInfo->getKeyCount() + keyId;
-        return min(mSampledNormalizedSquaredLengthCache[index], mMaxPointToKeyLength);
+        return std::min(mSampledNormalizedSquaredLengthCache[index], mMaxPointToKeyLength);
     }
     if (CharUtils::isIntentionalOmissionCodePoint(codePoint)) {
         return 0.0f;
diff --git a/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
index f846154..867f598 100644
--- a/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
@@ -241,7 +241,7 @@
         // Calculate velocity by using distances and durations of
         // ProximityInfoParams::NUM_POINTS_FOR_SPEED_CALCULATION points for both forward and
         // backward.
-        const int forwardNumPoints = min(inputSize - 1,
+        const int forwardNumPoints = std::min(inputSize - 1,
                 index + ProximityInfoParams::NUM_POINTS_FOR_SPEED_CALCULATION);
         for (int j = index; j < forwardNumPoints; ++j) {
             if (i < sampledInputSize - 1 && j >= (*sampledInputIndice)[i + 1]) {
@@ -251,7 +251,7 @@
                     xCoordinates[j + 1], yCoordinates[j + 1]);
             duration += times[j + 1] - times[j];
         }
-        const int backwardNumPoints = max(0,
+        const int backwardNumPoints = std::max(0,
                 index - ProximityInfoParams::NUM_POINTS_FOR_SPEED_CALCULATION);
         for (int j = index - 1; j >= backwardNumPoints; --j) {
             if (i > 0 && j < (*sampledInputIndice)[i - 1]) {
@@ -273,7 +273,7 @@
 
     // Direction calculation.
     sampledDirections->resize(sampledInputSize - 1);
-    for (int i = max(0, lastSavedInputSize - 1); i < sampledInputSize - 1; ++i) {
+    for (int i = std::max(0, lastSavedInputSize - 1); i < sampledInputSize - 1; ++i) {
         (*sampledDirections)[i] = getDirection(sampledInputXs, sampledInputYs, i, i + 1);
     }
     return averageSpeed;
@@ -610,7 +610,7 @@
         const int inputIndex, const int keyId) {
     if (keyId != NOT_AN_INDEX) {
         const int index = inputIndex * keyCount + keyId;
-        return min((*sampledNormalizedSquaredLengthCache)[index], maxPointToKeyLength);
+        return std::min((*sampledNormalizedSquaredLengthCache)[index], maxPointToKeyLength);
     }
     // If the char is not a key on the keyboard then return the max length.
     return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
@@ -651,13 +651,13 @@
         }
 
         if (i == 0) {
-            skipProbability *= min(1.0f,
+            skipProbability *= std::min(1.0f,
                     nearestKeyDistance * ProximityInfoParams::NEAREST_DISTANCE_WEIGHT
                             + ProximityInfoParams::NEAREST_DISTANCE_BIAS);
             // Promote the first point
             skipProbability *= ProximityInfoParams::SKIP_FIRST_POINT_PROBABILITY;
         } else if (i == sampledInputSize - 1) {
-            skipProbability *= min(1.0f,
+            skipProbability *= std::min(1.0f,
                     nearestKeyDistance * ProximityInfoParams::NEAREST_DISTANCE_WEIGHT_FOR_LAST
                             + ProximityInfoParams::NEAREST_DISTANCE_BIAS_FOR_LAST);
             // Promote the last point
@@ -668,17 +668,17 @@
                     && speedRate
                             < (*sampledSpeedRates)[i + 1] - ProximityInfoParams::SPEED_MARGIN) {
                 if (currentAngle < ProximityInfoParams::CORNER_ANGLE_THRESHOLD) {
-                    skipProbability *= min(1.0f, speedRate
+                    skipProbability *= std::min(1.0f, speedRate
                             * ProximityInfoParams::SLOW_STRAIGHT_WEIGHT_FOR_SKIP_PROBABILITY);
                 } else {
                     // If the angle is small enough, we promote this point more. (e.g. pit vs put)
-                    skipProbability *= min(1.0f,
+                    skipProbability *= std::min(1.0f,
                             speedRate * ProximityInfoParams::SPEED_WEIGHT_FOR_SKIP_PROBABILITY
                                     + ProximityInfoParams::MIN_SPEED_RATE_FOR_SKIP_PROBABILITY);
                 }
             }
 
-            skipProbability *= min(1.0f,
+            skipProbability *= std::min(1.0f,
                     speedRate * nearestKeyDistance * ProximityInfoParams::NEAREST_DISTANCE_WEIGHT
                             + ProximityInfoParams::NEAREST_DISTANCE_BIAS);
 
@@ -708,10 +708,10 @@
         // (1.0f - skipProbability).
         const float inputCharProbability = 1.0f - skipProbability;
 
-        const float speedxAngleRate = min(speedRate * currentAngle / M_PI_F
+        const float speedxAngleRate = std::min(speedRate * currentAngle / M_PI_F
                 * ProximityInfoParams::SPEEDxANGLE_WEIGHT_FOR_STANDARD_DEVIATION,
                         ProximityInfoParams::MAX_SPEEDxANGLE_RATE_FOR_STANDARD_DEVIATION);
-        const float speedxNearestKeyDistanceRate = min(speedRate * nearestKeyDistance
+        const float speedxNearestKeyDistanceRate = std::min(speedRate * nearestKeyDistance
                 * ProximityInfoParams::SPEEDxNEAREST_WEIGHT_FOR_STANDARD_DEVIATION,
                         ProximityInfoParams::MAX_SPEEDxNEAREST_RATE_FOR_STANDARD_DEVIATION);
         const float sigma = speedxAngleRate + speedxNearestKeyDistanceRate
@@ -828,7 +828,7 @@
 
     // Decrease key probabilities of points which don't have the highest probability of that key
     // among nearby points. Probabilities of the first point and the last point are not suppressed.
-    for (int i = max(start, 1); i < sampledInputSize; ++i) {
+    for (int i = std::max(start, 1); i < sampledInputSize; ++i) {
         for (int j = i + 1; j < sampledInputSize; ++j) {
             if (!suppressCharProbabilities(
                     mostCommonKeyWidth, sampledInputSize, sampledLengthCache, i, j,
@@ -836,7 +836,7 @@
                 break;
             }
         }
-        for (int j = i - 1; j >= max(start, 0); --j) {
+        for (int j = i - 1; j >= std::max(start, 0); --j) {
             if (!suppressCharProbabilities(
                     mostCommonKeyWidth, sampledInputSize, sampledLengthCache, i, j,
                     charProbabilities)) {
@@ -879,7 +879,7 @@
         if (i >= lastSavedInputSize) {
             (*sampledSearchKeySets)[i].reset();
         }
-        for (int j = max(i, lastSavedInputSize); j < sampledInputSize; ++j) {
+        for (int j = std::max(i, lastSavedInputSize); j < sampledInputSize; ++j) {
             // TODO: Investigate if this is required. This may not fail.
             if ((*sampledLengthCache)[j] - (*sampledLengthCache)[i] >= readForwordLength) {
                 break;
@@ -930,7 +930,7 @@
             (*charProbabilities)[index0][NOT_AN_INDEX] += suppression;
 
             // Add the probability of the same key nearby index1
-            const float probabilityGain = min(suppression
+            const float probabilityGain = std::min(suppression
                     * ProximityInfoParams::SUPPRESSION_WEIGHT_FOR_PROBABILITY_GAIN,
                     (*charProbabilities)[index1][NOT_AN_INDEX]
                             * ProximityInfoParams::SKIP_PROBABALITY_WEIGHT_FOR_PROBABILITY_GAIN);
diff --git a/native/jni/src/suggest/core/layout/proximity_info_utils.h b/native/jni/src/suggest/core/layout/proximity_info_utils.h
index 6d2c11b..310bbdb 100644
--- a/native/jni/src/suggest/core/layout/proximity_info_utils.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_utils.h
@@ -100,6 +100,10 @@
         const float dotProduct = ray1x * ray2x + ray1y * ray2y;
         const float lineLengthSqr = GeometryUtils::SQUARE_FLOAT(ray2x)
                 + GeometryUtils::SQUARE_FLOAT(ray2y);
+        if (lineLengthSqr <= 0.0f) {
+            // Return point to the point distance.
+            return getSquaredDistanceFloat(x, y, x1, y1);
+        }
         const float projectionLengthSqr = dotProduct / lineLengthSqr;
 
         float projectionX;
@@ -125,7 +129,7 @@
     struct NormalDistribution {
      public:
         NormalDistribution(const float u, const float sigma)
-                : mU(u), mSigma(sigma),
+                : mU(u),
                   mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F
                           * GeometryUtils::SQUARE_FLOAT(sigma))),
                   mPreComputedExponentPart(-1.0f / (2.0f * GeometryUtils::SQUARE_FLOAT(sigma))) {}
@@ -139,7 +143,6 @@
      private:
         DISALLOW_IMPLICIT_CONSTRUCTORS(NormalDistribution);
         const float mU; // mean value
-        const float mSigma; // standard deviation
         const float mPreComputedNonExpPart; // = 1 / sqrt(2 * PI * sigma^2)
         const float mPreComputedExponentPart; // = -1 / (2 * sigma^2)
     }; // struct NormalDistribution
diff --git a/native/jni/src/suggest/core/layout/touch_position_correction_utils.h b/native/jni/src/suggest/core/layout/touch_position_correction_utils.h
index 9130e87..14074c1 100644
--- a/native/jni/src/suggest/core/layout/touch_position_correction_utils.h
+++ b/native/jni/src/suggest/core/layout/touch_position_correction_utils.h
@@ -17,6 +17,8 @@
 #ifndef LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
 #define LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
 
+#include <algorithm>
+
 #include "defines.h"
 #include "suggest/core/layout/proximity_info_params.h"
 
@@ -34,7 +36,7 @@
         static const float R2 = 1.0f;
         const float x = normalizedSquaredDistance;
         if (!isTouchPositionCorrectionEnabled) {
-            return min(C, x);
+            return std::min(C, x);
         }
 
         // factor is a piecewise linear function like:
diff --git a/native/jni/src/suggest/core/result/suggestions_output_utils.cpp b/native/jni/src/suggest/core/result/suggestions_output_utils.cpp
index e9fb3b8..19912f2 100644
--- a/native/jni/src/suggest/core/result/suggestions_output_utils.cpp
+++ b/native/jni/src/suggest/core/result/suggestions_output_utils.cpp
@@ -16,6 +16,8 @@
 
 #include "suggest/core/result/suggestions_output_utils.h"
 
+#include <algorithm>
+
 #include "suggest/core/dicnode/dic_node.h"
 #include "suggest/core/dicnode/dic_node_utils.h"
 #include "suggest/core/dictionary/binary_dictionary_shortcut_iterator.h"
@@ -36,7 +38,7 @@
 #if DEBUG_EVALUATE_MOST_PROBABLE_STRING
     const int terminalSize = 0;
 #else
-    const int terminalSize = min(MAX_RESULTS,
+    const int terminalSize = std::min(MAX_RESULTS,
             static_cast<int>(traverseSession->getDicTraverseCache()->terminalSize()));
 #endif
     DicNode terminals[MAX_RESULTS]; // Avoiding non-POD variable length array
@@ -245,12 +247,12 @@
             // shortcut entry's score == its base entry's score - 1
             shortcutScore = finalScore;
             // Protection against int underflow
-            shortcutScore = max(S_INT_MIN + 1, shortcutScore) - 1;
+            shortcutScore = std::max(S_INT_MIN + 1, shortcutScore) - 1;
             kind = Dictionary::KIND_SHORTCUT;
         }
         outputTypes[outputWordIndex] = kind;
         outputScores[outputWordIndex] = shortcutScore;
-        outputScores[outputWordIndex] = max(S_INT_MIN + 1, shortcutScore) - 1;
+        outputScores[outputWordIndex] = std::max(S_INT_MIN + 1, shortcutScore) - 1;
         const int startIndex2 = outputWordIndex * MAX_WORD_LENGTH;
         DicNodeUtils::appendTwoWords(0, 0, shortcutTarget, shortcutTargetStringLength,
                 &outputCodePoints[startIndex2]);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
index 7c7b05c..ecc9fda 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
@@ -16,6 +16,8 @@
 
 #include "suggest/policyimpl/dictionary/header/header_policy.h"
 
+#include <algorithm>
+
 namespace latinime {
 
 // Note that these are corresponding definitions in Java side in DictionaryHeader.
@@ -72,7 +74,7 @@
         outValue[1] = '\0';
         return;
     }
-    const int terminalIndex = min(static_cast<int>(it->second.size()), outValueSize - 1);
+    const int terminalIndex = std::min(static_cast<int>(it->second.size()), outValueSize - 1);
     for (int i = 0; i < terminalIndex; ++i) {
         outValue[i] = it->second[i];
     }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h
index ae863af..f2fa5b7 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h
@@ -31,8 +31,7 @@
  public:
     Ver4ShortcutListPolicy(ShortcutDictContent *const shortcutDictContent,
             const TerminalPositionLookupTable *const terminalPositionLookupTable)
-            : mShortcutDictContent(shortcutDictContent),
-              mTerminalPositionLookupTable(terminalPositionLookupTable) {}
+            : mShortcutDictContent(shortcutDictContent) {}
 
     ~Ver4ShortcutListPolicy() {}
 
@@ -104,7 +103,6 @@
     DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4ShortcutListPolicy);
 
     ShortcutDictContent *const mShortcutDictContent;
-    const TerminalPositionLookupTable *const mTerminalPositionLookupTable;
 };
 } // namespace latinime
 #endif // LATINIME_VER4_SHORTCUT_LIST_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
index 35e05d7..bac4d4e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
@@ -16,6 +16,7 @@
 
 #include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
 
+#include <algorithm>
 #include <cmath>
 #include <stdlib.h>
 
@@ -72,7 +73,7 @@
             headerPolicy->getForgettingCurveDurationToLevelDown());
     return sProbabilityTable.getProbability(
             headerPolicy->getForgettingCurveProbabilityValuesTableId(), historicalInfo->getLevel(),
-            min(max(elapsedTimeStepCount, 0), MAX_ELAPSED_TIME_STEP_COUNT));
+            std::min(std::max(elapsedTimeStepCount, 0), MAX_ELAPSED_TIME_STEP_COUNT));
 }
 
 /* static */ int ForgettingCurveUtils::getProbability(const int unigramProbability,
@@ -80,11 +81,11 @@
     if (unigramProbability == NOT_A_PROBABILITY) {
         return NOT_A_PROBABILITY;
     } else if (bigramProbability == NOT_A_PROBABILITY) {
-        return min(backoff(unigramProbability), MAX_PROBABILITY);
+        return std::min(backoff(unigramProbability), MAX_PROBABILITY);
     } else {
         // TODO: Investigate better way to handle bigram probability.
-        return min(max(unigramProbability, bigramProbability + MULTIPLIER_TWO_IN_PROBABILITY_SCALE),
-                MAX_PROBABILITY);
+        return std::min(std::max(unigramProbability,
+                bigramProbability + MULTIPLIER_TWO_IN_PROBABILITY_SCALE), MAX_PROBABILITY);
     }
 }
 
@@ -183,7 +184,7 @@
                                 -1.0f * static_cast<float>(timeStepCount)
                                         / static_cast<float>(MAX_ELAPSED_TIME_STEP_COUNT + 1));
                 mTables[tableId][level][timeStepCount] =
-                        min(max(static_cast<int>(probability), 1), MAX_PROBABILITY);
+                        std::min(std::max(static_cast<int>(probability), 1), MAX_PROBABILITY);
             }
         }
     }
diff --git a/native/jni/src/suggest/policyimpl/utils/edit_distance.h b/native/jni/src/suggest/policyimpl/utils/edit_distance.h
index 0871c37..4cfd0b3 100644
--- a/native/jni/src/suggest/policyimpl/utils/edit_distance.h
+++ b/native/jni/src/suggest/policyimpl/utils/edit_distance.h
@@ -17,6 +17,8 @@
 #ifndef LATINIME_EDIT_DISTANCE_H
 #define LATINIME_EDIT_DISTANCE_H
 
+#include <algorithm>
+
 #include "defines.h"
 #include "suggest/policyimpl/utils/edit_distance_policy.h"
 
@@ -38,13 +40,13 @@
 
         for (int i = 0; i < beforeLength; ++i) {
             for (int j = 0; j < afterLength; ++j) {
-                dp[(afterLength + 1) * (i + 1) + (j + 1)] = min(
+                dp[(afterLength + 1) * (i + 1) + (j + 1)] = std::min(
                         dp[(afterLength + 1) * i + (j + 1)] + policy->getInsertionCost(i, j),
-                        min(dp[(afterLength + 1) * (i + 1) + j] + policy->getDeletionCost(i, j),
-                                dp[(afterLength + 1) * i + j]
-                                        + policy->getSubstitutionCost(i, j)));
+                        std::min(
+                                dp[(afterLength + 1) * (i + 1) + j] + policy->getDeletionCost(i, j),
+                                dp[(afterLength + 1) * i + j] + policy->getSubstitutionCost(i, j)));
                 if (policy->allowTransposition(i, j)) {
-                    dp[(afterLength + 1) * (i + 1) + (j + 1)] = min(
+                    dp[(afterLength + 1) * (i + 1) + (j + 1)] = std::min(
                             dp[(afterLength + 1) * (i + 1) + (j + 1)],
                             dp[(afterLength + 1) * (i - 1) + (j - 1)]
                                     + policy->getTranspositionCost(i, j));
diff --git a/native/jni/src/utils/autocorrection_threshold_utils.cpp b/native/jni/src/utils/autocorrection_threshold_utils.cpp
index 1f8ee08..349786a 100644
--- a/native/jni/src/utils/autocorrection_threshold_utils.cpp
+++ b/native/jni/src/utils/autocorrection_threshold_utils.cpp
@@ -16,6 +16,7 @@
 
 #include "utils/autocorrection_threshold_utils.h"
 
+#include <algorithm>
 #include <cmath>
 
 #include "defines.h"
@@ -99,7 +100,7 @@
     const float maxScore = score >= S_INT_MAX ? static_cast<float>(S_INT_MAX)
             : static_cast<float>(MAX_INITIAL_SCORE)
                     * powf(static_cast<float>(TYPED_LETTER_MULTIPLIER),
-                            static_cast<float>(min(beforeLength, afterLength - spaceCount)))
+                            static_cast<float>(std::min(beforeLength, afterLength - spaceCount)))
                     * static_cast<float>(FULL_WORD_MULTIPLIER);
 
     return (static_cast<float>(score) / maxScore) * weight;
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/AlphabetShifted.java b/tests/src/com/android/inputmethod/keyboard/layout/AlphabetShifted.java
new file mode 100644
index 0000000..be3ed12
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/AlphabetShifted.java
@@ -0,0 +1,46 @@
+/*
+ * 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.layout;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.expected.LayoutBase;
+import com.android.inputmethod.latin.Constants;
+
+import java.util.Locale;
+
+/**
+ * The generic upper case alphabet keyboard layout.
+ */
+public final class AlphabetShifted extends LayoutBase {
+    public static ExpectedKey[][] getAlphabet(final ExpectedKey[][] lowerCaseKeyboard,
+            final Locale locale) {
+        final ExpectedKey[][] upperCaseKeyboard = ExpectedKeyboardBuilder.toUpperCase(
+                lowerCaseKeyboard, locale);
+        return new ExpectedKeyboardBuilder(upperCaseKeyboard)
+                .replaceKeyOfAll(SHIFT_KEY, SHIFTED_SHIFT_KEY)
+                .build();
+    }
+
+    // Icon id.
+    private static final int ICON_SHIFTED_SHIFT = KeyboardIconsSet.getIconId("shift_key_shifted");
+
+    // Functional key.
+    private static final ExpectedKey SHIFTED_SHIFT_KEY = key(
+            ICON_SHIFTED_SHIFT, Constants.CODE_SHIFT, CAPSLOCK_MORE_KEY);
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java
new file mode 100644
index 0000000..f7179b7
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java
@@ -0,0 +1,46 @@
+/*
+ * 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.layout;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.expected.LayoutBase;
+
+/**
+ * The QWERTY alphabet keyboard.
+ */
+public final class Qwerty extends LayoutBase {
+    public static ExpectedKey[][] getAlphabet(final boolean isPhone) {
+        return toCommonAlphabet(ALPHABET_COMMON, isPhone);
+    }
+
+    private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder(10, 9, 7, 3)
+            .setLabelsOfRow(1, "q", "w", "e", "r", "t", "y", "u", "i", "o", "p")
+            .setMoreKeysOf("q", "1")
+            .setMoreKeysOf("w", "2")
+            .setMoreKeysOf("e", "3")
+            .setMoreKeysOf("r", "4")
+            .setMoreKeysOf("t", "5")
+            .setMoreKeysOf("y", "6")
+            .setMoreKeysOf("u", "7")
+            .setMoreKeysOf("i", "8")
+            .setMoreKeysOf("o", "9")
+            .setMoreKeysOf("p", "0")
+            .setLabelsOfRow(2, "a", "s", "d", "f", "g", "h", "j", "k", "l")
+            .setLabelsOfRow(3, "z", "x", "c", "v", "b", "n", "m")
+            .build();
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
new file mode 100644
index 0000000..03d7f07
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
@@ -0,0 +1,187 @@
+/*
+ * 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.layout;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.expected.LayoutBase;
+import com.android.inputmethod.latin.Constants;
+
+/**
+ * The symbols keyboard layout.
+ */
+public final class Symbols extends LayoutBase {
+    public static ExpectedKey[][] getSymbols(final boolean isPhone) {
+        return isPhone ? toPhoneSymbol(SYMBOLS_COMMON) : toTabletSymbols(SYMBOLS_COMMON);
+    }
+
+    // Functional keys.
+    public static final ExpectedKey ALPHABET_KEY = key("ABC", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+    public static final ExpectedKey SYMBOLS_SHIFT_KEY = key("= \\ <", Constants.CODE_SHIFT);
+    public static final ExpectedKey TABLET_SYMBOLS_SHIFT_KEY = key("~ [ <", Constants.CODE_SHIFT);
+
+    // Common symbols keyboard layout.
+    public static final ExpectedKey[][] SYMBOLS_COMMON = new ExpectedKeyboardBuilder(10, 9, 7, 5)
+            .setLabelsOfRow(1, "1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
+            // U+00B9: "¹" SUPERSCRIPT ONE
+            // U+00BD: "½" VULGAR FRACTION ONE HALF
+            // U+2153: "⅓" VULGAR FRACTION ONE THIRD
+            // U+00BC: "¼" VULGAR FRACTION ONE QUARTER
+            // U+215B: "⅛" VULGAR FRACTION ONE EIGHTH
+            .setMoreKeysOf("1", "\u00B9", "\u00BD", "\u2153", "\u00BC", "\u215B")
+            // U+00B2: "²" SUPERSCRIPT TWO
+            // U+2154: "⅔" VULGAR FRACTION TWO THIRDS
+            .setMoreKeysOf("2", "\u00B2", "\u2154")
+            // U+00B3: "³" SUPERSCRIPT THREE
+            // U+00BE: "¾" VULGAR FRACTION THREE QUARTERS
+            // U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS
+            .setMoreKeysOf("3", "\u00B3", "\u00BE", "\u215C")
+            // U+2074: "⁴" SUPERSCRIPT FOUR
+            .setMoreKeysOf("4", "\u2074")
+            // U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS
+            .setMoreKeysOf("5", "\u215D")
+            // U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS
+            .setMoreKeysOf("7", "\u215E")
+            // U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N
+            // U+2205: "∅" EMPTY SET
+            .setMoreKeysOf("0", "\u207F", "\u2205")
+            .setLabelsOfRow(2, "@", "#", "$", "%", "&", "-", "+", "(", ")")
+            // U+00A2: "¢" CENT SIGN
+            // U+00A3: "£" POUND SIGN
+            // U+20AC: "€" EURO SIGN
+            // U+00A5: "¥" YEN SIGN
+            // U+20B1: "₱" PESO SIGN
+            .setMoreKeysOf("$", "\u00A2", "\u00A3", "\u20AC", "\u00A5", "\u20B1")
+            // U+2030: "‰" PER MILLE SIGN
+            .setMoreKeysOf("%", "\u2030")
+            // U+2013: "–" EN DASH
+            // U+2014: "—" EM DASH
+            // U+00B7: "·" MIDDLE DOT
+            .setMoreKeysOf("-", "_", "\u2013", "\u2014", "\u00B7")
+            // U+00B1: "±" PLUS-MINUS SIGN
+            .setMoreKeysOf("+", "\u00B1")
+            .setMoreKeysOf("(", "<", "{", "[")
+            .setMoreKeysOf(")", ">", "}", "]")
+            .setLabelsOfRow(3, "*", "\"", "'", ":", ";", "!", "?")
+            // U+2020: "†" DAGGER
+            // U+2021: "‡" DOUBLE DAGGER
+            // U+2605: "★" BLACK STAR
+            .setMoreKeysOf("*", "\u2020", "\u2021", "\u2605")
+            // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+            // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+            // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+            // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+            // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+            .setMoreKeysOf("\"", "\u201E", "\u201C", "\u201D", "\u00AB", "\u00BB")
+            // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+            // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+            // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+            // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+            // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+            .setMoreKeysOf("'", "\u201A", "\u2018", "\u2019", "\u2039", "\u203A")
+            // U+00A1: "¡" INVERTED EXCLAMATION MARK
+            .setMoreKeysOf("!", "\u00A1")
+            // U+00BF: "¿" INVERTED QUESTION MARK
+            .setMoreKeysOf("?", "\u00BF")
+            .setLabelsOfRow(4, "_", "/", " ", ",", ".")
+            // U+2026: "…" HORIZONTAL ELLIPSIS
+            .setMoreKeysOf(".", "\u2026")
+            .build();
+
+    private static ExpectedKey[][] toPhoneSymbol(final ExpectedKey[][] common) {
+        return new ExpectedKeyboardBuilder(common)
+                .addKeysOnTheLeftOfRow(3, Symbols.SYMBOLS_SHIFT_KEY)
+                .addKeysOnTheRightOfRow(3, DELETE_KEY)
+                .addKeysOnTheLeftOfRow(4, Symbols.ALPHABET_KEY)
+                .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY))
+                .build();
+    }
+
+    private static ExpectedKey[][] toTabletSymbols(final ExpectedKey[][] common) {
+        return new ExpectedKeyboardBuilder(common)
+                .addKeysOnTheLeftOfRow(3,
+                        key("\\"), key("="))
+                .addKeysOnTheRightOfRow(1, DELETE_KEY)
+                .addKeysOnTheRightOfRow(2, ENTER_KEY)
+                .addKeysOnTheLeftOfRow(3, Symbols.TABLET_SYMBOLS_SHIFT_KEY)
+                .addKeysOnTheRightOfRow(3, Symbols.TABLET_SYMBOLS_SHIFT_KEY)
+                .addKeysOnTheLeftOfRow(4, Symbols.ALPHABET_KEY)
+                .addKeysOnTheRightOfRow(4, EMOJI_KEY)
+                .build();
+    }
+
+    // Helper method to add currency symbols for Euro.
+    public static ExpectedKeyboardBuilder euro(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+20AC: "€" EURO SIGN
+                // U+00A2: "¢" CENT SIGN
+                // U+00A3: "£" POUND SIGN
+                // U+00A5: "¥" YEN SIGN
+                // U+20B1: "₱" PESO SIGN
+                .replaceKeyOfLabel("$", key("\u20AC",
+                        moreKey("\u00A2"), moreKey("\u00A3"), moreKey("$"),
+                        moreKey("\u00A5"), moreKey("\u20B1")));
+    }
+
+    // Helper method to add single quotes "more keys".
+    // "9LLR" means "9-low/Left quotation marks, Left/Right-pointing angle quotation marks".
+    public static ExpectedKeyboardBuilder singleQuotes9LLR(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+                // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+                // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+                // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+                // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+                .setMoreKeysOf("'", "\u2019", "\u201A", "\u2018", "\u2039", "\u203A");
+    }
+
+    // Helper method to add single quotes "more keys".
+    // "9LLR" means "9-low/Left quotation marks, Right/Left-pointing angle quotation marks".
+    public static ExpectedKeyboardBuilder singleQuotes9LRL(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+                // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+                // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+                // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+                // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+                .setMoreKeysOf("'", "\u2019", "\u201A", "\u2018", "\u203A", "\u2039");
+    }
+
+    // Helper method to add double quotes "more keys".
+    // "9LLR" means "9-low/Left quotation marks, Left/Right-pointing angle quotation marks".
+    public static ExpectedKeyboardBuilder doubleQuotes9LLR(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+                // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+                // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+                // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+                // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+                .setMoreKeysOf("\"", "\u201D", "\u201E", "\u201C", "\u00AB", "\u00BB");
+    }
+
+    // Helper method to add double quotes "more keys".
+    // "9LLR" means "9-low/Left quotation marks, Right/Left-pointing angle quotation marks".
+    public static ExpectedKeyboardBuilder doubleQuotes9LRL(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+                // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+                // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+                // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+                // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+                .setMoreKeysOf("\"", "\u201D", "\u201E", "\u201C", "\u00BB", "\u00AB");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
new file mode 100644
index 0000000..368f9db
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
@@ -0,0 +1,142 @@
+/*
+ * 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.layout;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.expected.LayoutBase;
+import com.android.inputmethod.latin.Constants;
+
+/**
+ * The symbols shifted keyboard layout.
+ */
+public final class SymbolsShifted extends LayoutBase {
+    public static ExpectedKey[][] getSymbolsShifted(final boolean isPhone) {
+        return isPhone ? toPhoneSymbolsShifted(SYMBOLS_SHIFTED_COMMON)
+                : toTabletSymbolsShifted(SYMBOLS_SHIFTED_COMMON);
+    }
+
+    // Functional key.
+    public static final ExpectedKey BACK_TO_SYMBOLS_KEY = key("?123", Constants.CODE_SHIFT);
+
+    // Common symbols shifted keyboard layout.
+    public static final ExpectedKey[][] SYMBOLS_SHIFTED_COMMON =
+            new ExpectedKeyboardBuilder(10, 9, 7, 5)
+            // U+0060: "`" GRAVE ACCENT
+            // U+2022: "•" BULLET
+            // U+221A: "√" SQUARE ROOT
+            // U+03C0: "π" GREEK SMALL LETTER PI
+            // U+00F7: "÷" DIVISION SIGN
+            // U+00D7: "×" MULTIPLICATION SIGN
+            // U+00B6: "¶" PILCROW SIGN
+            // U+2206: "∆" INCREMENT
+            .setLabelsOfRow(1,
+                    "~", "\u0060", "|", "\u2022", "\u221A",
+                    "\u03C0", "\u00F7", "\u00D7", "\u00B6", "\u2206")
+            // U+2022: "•" BULLET
+            // U+266A: "♪" EIGHTH NOTE
+            // U+2665: "♥" BLACK HEART SUIT
+            // U+2660: "♠" BLACK SPADE SUIT
+            // U+2666: "♦" BLACK DIAMOND SUIT
+            // U+2663: "♣" BLACK CLUB SUIT
+            .setMoreKeysOf("\u2022", "\u266A", "\u2665", "\u2660", "\u2666", "\u2663")
+            // U+03C0: "π" GREEK SMALL LETTER PI
+            // U+03A0: "Π" GREEK CAPITAL LETTER PI
+            .setMoreKeysOf("\u03C0", "\u03A0")
+            // U+00B6: "¶" PILCROW SIGN
+            // U+00A7: "§" SECTION SIGN
+            .setMoreKeysOf("\u00B6", "\u00A7")
+            // U+00A3: "£" POUND SIGN
+            // U+00A2: "¢" CENT SIGN
+            // U+20AC: "€" EURO SIGN
+            // U+00A5: "¥" YEN SIGN
+            // U+00B0: "°" DEGREE SIGN
+            .setLabelsOfRow(2,
+                    "\u00A3", "\u00A2", "\u20AC", "\u00A5", "^",
+                    "\u00B0", "=", "{", "}")
+            // U+2191: "↑" UPWARDS ARROW
+            // U+2193: "↓" DOWNWARDS ARROW
+            // U+2190: "←" LEFTWARDS ARROW
+            // U+2192: "→" RIGHTWARDS ARROW
+            .setMoreKeysOf("^", "\u2191", "\u2193", "\u2190", "\u2192")
+            // U+00B0: "°" DEGREE SIGN
+            // U+2032: "′" PRIME
+            // U+2033: "″" DOUBLE PRIME
+            .setMoreKeysOf("\u00B0", "\u2032", "\u2033")
+            // U+2260: "≠" NOT EQUAL TO
+            // U+2248: "≈" ALMOST EQUAL TO
+            // U+221E: "∞" INFINITY
+            .setMoreKeysOf("=", "\u2260", "\u2248", "\u221E")
+            // U+00A9: "©" COPYRIGHT SIGN
+            // U+00AE: "®" REGISTERED SIGN
+            // U+2122: "™" TRADE MARK SIGN
+            // U+2105: "℅" CARE OF
+            .setLabelsOfRow(3,
+                    "\\", "\u00A9", "\u00AE", "\u2122", "\u2105",
+                    "[", "]")
+            .setLabelsOfRow(4,
+                    "<", ">", " ", ",", ".")
+            // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+            // U+2264: "≤" LESS-THAN OR EQUAL TO
+            // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+            .setMoreKeysOf("<", "\u2039", "\u2264", "\u00AB")
+            // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+            // U+2265: "≥" GREATER-THAN EQUAL TO
+            // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+            .setMoreKeysOf(">", "\u203A", "\u2265", "\u00BB")
+            // U+2026: "…" HORIZONTAL ELLIPSIS
+            .setMoreKeysOf(".", "\u2026")
+            .build();
+
+    private static ExpectedKey[][] toPhoneSymbolsShifted(final ExpectedKey[][] common) {
+        return new ExpectedKeyboardBuilder(common)
+                .addKeysOnTheLeftOfRow(3, BACK_TO_SYMBOLS_KEY)
+                .addKeysOnTheRightOfRow(3, DELETE_KEY)
+                .addKeysOnTheLeftOfRow(4, Symbols.ALPHABET_KEY)
+                .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY))
+                .build();
+    }
+
+    private static ExpectedKey[][] toTabletSymbolsShifted(final ExpectedKey[][] common) {
+        return new ExpectedKeyboardBuilder(common)
+                // U+00BF: "¿" INVERTED QUESTION MARK
+                // U+00A1: "¡" INVERTED EXCLAMATION MARK
+                .addKeysOnTheRightOfRow(3,
+                        key("\u00A1"), key("\u00BF"))
+                .addKeysOnTheRightOfRow(1, DELETE_KEY)
+                .addKeysOnTheRightOfRow(2, ENTER_KEY)
+                .addKeysOnTheLeftOfRow(3, BACK_TO_SYMBOLS_KEY)
+                .addKeysOnTheRightOfRow(3, BACK_TO_SYMBOLS_KEY)
+                .addKeysOnTheLeftOfRow(4, Symbols.ALPHABET_KEY)
+                .addKeysOnTheRightOfRow(4, EMOJI_KEY)
+                .build();
+    }
+
+    // Helper method to add currency symbols for Euro.
+    public static ExpectedKeyboardBuilder euro(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00A5: "¥" YEN SIGN
+                // U+00A2: "¢" CENT SIGN
+                .replaceKeyOfLabel("\u00A5", key("\u00A2"))
+                // U+20AC: "€" EURO SIGN
+                // U+00A2: "¢" CENT SIGN
+                .replaceKeyOfLabel("\u20AC", key("$", moreKey("\u00A2")))
+                // U+00A2: "¢" CENT SIGN
+                // U+00A5: "¥" YEN SIGN
+                .replaceKeyOfLabel("\u00A2", key("\u00A5"));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ActualKeyboardBuilder.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ActualKeyboardBuilder.java
new file mode 100644
index 0000000..b918d47
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ActualKeyboardBuilder.java
@@ -0,0 +1,189 @@
+/*
+ * 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.layout.expected;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.keyboard.internal.MoreKeySpec;
+import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+import com.android.inputmethod.latin.utils.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+
+/**
+ * This class builds an actual keyboard for unit test.
+ */
+public final class ActualKeyboardBuilder extends AbstractKeyboardBuilder<Key> {
+    // Comparator to sort {@link Key}s from top-left to bottom-right order.
+    private static final Comparator<Key> ROW_COLUMN_COMPARATOR = new Comparator<Key>() {
+        @Override
+        public int compare(final Key lhs, final Key rhs) {
+            if (lhs.getY() < rhs.getY()) return -1;
+            if (lhs.getY() > rhs.getY()) return 1;
+            if (lhs.getX() < rhs.getX()) return -1;
+            if (lhs.getX() > rhs.getX()) return 1;
+            return 0;
+        }
+    };
+
+    /**
+     * Create the keyboard that consists of the array of rows of the actual keyboard's keys.
+     * @param keys the array of keys of the actual keyboard.
+     * @return the actual keyboard grouped with rows.
+     */
+    public static Key[][] buildKeyboard(final Key[] keys) {
+        // Sort keys from top-left to bottom-right order to prepare to create rows.
+        final ArrayList<Key> sortedKeys = CollectionUtils.newArrayList(Arrays.asList(keys));
+        Collections.sort(sortedKeys, ROW_COLUMN_COMPARATOR);
+
+        // Grouping keys into rows.
+        final ArrayList<ArrayList<Key>> rows = CollectionUtils.newArrayList();
+        ArrayList<Key> elements = CollectionUtils.newArrayList();
+        int lastY = sortedKeys.get(0).getY();
+        for (final Key key : sortedKeys) {
+            if (lastY != key.getY()) {
+                // A new row is starting.
+                lastY = key.getY();
+                rows.add(elements);
+                elements = CollectionUtils.newArrayList();
+            }
+            elements.add(key);
+        }
+        rows.add(elements); // Add the last row.
+
+        // Calculate each dimension of rows and create a builder.
+        final int[] dimensions = new int[rows.size()];
+        for (int rowIndex = 0; rowIndex < dimensions.length; rowIndex++) {
+            dimensions[rowIndex] = rows.get(rowIndex).size();
+        }
+        final ActualKeyboardBuilder builder = new ActualKeyboardBuilder(dimensions);
+
+        for (int rowIndex = 0; rowIndex < rows.size(); rowIndex++) {
+            final int row = rowIndex + 1;
+            final ArrayList<Key> rowKeys = rows.get(rowIndex);
+            builder.setRowAt(row, rowKeys.toArray(new Key[rowKeys.size()]));
+        }
+        return builder.build();
+    }
+
+    private ActualKeyboardBuilder(final int ... dimensions) {
+        super(dimensions);
+    }
+
+    @Override
+    Key defaultElement() { return null; }
+
+    @Override
+    Key[] newArray(final int size) { return new Key[size]; }
+
+    @Override
+    Key[][] newArrayOfArray(final int size) { return new Key[size][]; }
+
+    // Helper class to create concise representation from the key specification.
+    static class MoreKeySpecStringizer extends StringUtils.Stringizer<MoreKeySpec> {
+        static final MoreKeySpecStringizer STRINGIZER = new MoreKeySpecStringizer();
+
+        @Override
+        public String stringize(final MoreKeySpec spec) {
+            return toString(spec.mLabel, spec.mIconId, spec.mOutputText, spec.mCode);
+        }
+
+        static String toString(final String label, final int iconId, final String outputText,
+                final int code) {
+            final String visual = (iconId != KeyboardIconsSet.ICON_UNDEFINED)
+                    ? KeyboardIconsSet.getIconName(iconId) : label;
+            final String output;
+            if (code == Constants.CODE_OUTPUT_TEXT) {
+                output = outputText;
+            } else if (code < Constants.CODE_SPACE) {
+                output = Constants.printableCode(code);
+            } else {
+                output = StringUtils.newSingleCodePointString(code);
+            }
+            if (visual.equals(output)) {
+                return visual;
+            }
+            return visual + "|" + output;
+        }
+    }
+
+    // Helper class to create concise representation from the key.
+    static class KeyStringizer extends StringUtils.Stringizer<Key> {
+        static final KeyStringizer STRINGIZER = new KeyStringizer();
+
+        @Override
+        public String stringize(final Key key) {
+            if (key == null) {
+                return "NULL";
+            }
+            if (key.isSpacer()) {
+                return "SPACER";
+            }
+            final StringBuilder sb = new StringBuilder();
+            sb.append(MoreKeySpecStringizer.toString(
+                    key.getLabel(), key.getIconId(), key.getOutputText(), key.getCode()));
+            final MoreKeySpec[] moreKeys = key.getMoreKeys();
+            if (moreKeys == null) {
+                return sb.toString();
+            }
+            sb.append("^");
+            sb.append(MoreKeySpecStringizer.STRINGIZER.join(moreKeys));
+            return sb.toString();
+        }
+    }
+
+    /**
+     * Convert the key to human readable string.
+     * @param key the key to be converted to string.
+     * @return the human readable representation of <code>key</code>.
+     */
+    public static String toString(final Key key) {
+        return KeyStringizer.STRINGIZER.stringize(key);
+    }
+
+    /**
+     * Convert the keyboard row to human readable string.
+     * @param keys the keyboard row to be converted to string.
+     * @return the human readable representation of <code>keys</code>.
+     */
+    public static String toString(final Key[] keys) {
+        return KeyStringizer.STRINGIZER.join(keys);
+    }
+
+    // Helper class to create concise representation from the array of the key.
+    static class KeyArrayStringizer extends StringUtils.Stringizer<Key[]> {
+        static final KeyArrayStringizer STRINGIZER = new KeyArrayStringizer();
+
+        @Override
+        public String stringize(final Key[] keyArray) {
+            return KeyStringizer.STRINGIZER.join(keyArray);
+        }
+    }
+
+    /**
+     * Convert the keyboard to human readable string.
+     * @param rows the keyboard to be converted to string.
+     * @return the human readable representation of <code>rows</code>.
+     */
+    public static String toString(final Key[][] rows) {
+        return KeyArrayStringizer.STRINGIZER.join(rows, "\n" /* delimiter */);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/LayoutBase.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/LayoutBase.java
new file mode 100644
index 0000000..1aeb8c0
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/LayoutBase.java
@@ -0,0 +1,143 @@
+/*
+ * 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.layout.expected;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.Constants;
+
+/**
+ * Base class to create an expected keyboard for unit test.
+ */
+public class LayoutBase {
+    // Those helper methods have a lower case name to be readable when defining expected keyboard
+    // layouts.
+
+    // Helper method to create {@link ExpectedKey} object that has the label.
+    public static ExpectedKey key(final String label, final ExpectedKey ... moreKeys) {
+        return ExpectedKey.newInstance(label, moreKeys);
+    }
+
+    // Helper method to create {@link ExpectedKey} object that has the label and the output text.
+    public static ExpectedKey key(final String label, final String outputText,
+            final ExpectedKey ... moreKeys) {
+        return ExpectedKey.newInstance(label, outputText, moreKeys);
+    }
+
+    // Helper method to create {@link ExpectedKey} object that has the label and the output code.
+    public static ExpectedKey key(final String label, final int code,
+            final ExpectedKey ... moreKeys) {
+        return ExpectedKey.newInstance(label, code, moreKeys);
+    }
+
+    // Helper method to create {@link ExpectedKey} object that has the icon and the output code.
+    public static ExpectedKey key(final int iconId, final int code,
+            final ExpectedKey ... moreKeys) {
+        return ExpectedKey.newInstance(iconId, code, moreKeys);
+    }
+
+    // Helper method to create {@link ExpectedKey} object that has new "more keys".
+    public static ExpectedKey key(final ExpectedKey key, final ExpectedKey ... moreKeys) {
+        return ExpectedKey.newInstance(key.getVisual(), key.getOutput(), moreKeys);
+    }
+
+    // Helper method to create {@link ExpectedKey} object for "more key" that has the label.
+    public static ExpectedKey moreKey(final String label) {
+        return ExpectedKey.newInstance(label);
+    }
+
+    // Helper method to create {@link ExpectedKey} object for "more key" that has the label and the
+    // output text.
+    public static ExpectedKey moreKey(final String label, final String outputText) {
+        return ExpectedKey.newInstance(label, outputText);
+    }
+
+    // Helper method to create {@link ExpectedKey} object for "more key" that has the label and the
+    // output code.
+    public static ExpectedKey moreKey(final String label, final int code) {
+        return ExpectedKey.newInstance(label, code);
+    }
+
+    // Icon ids.
+    private static final int ICON_SHIFT = KeyboardIconsSet.getIconId("shift_key");
+    private static final int ICON_DELETE = KeyboardIconsSet.getIconId("delete_key");
+    private static final int ICON_SETTINGS = KeyboardIconsSet.getIconId("settings_key");
+    private static final int ICON_ENTER = KeyboardIconsSet.getIconId("enter_key");
+    private static final int ICON_EMOJI = KeyboardIconsSet.getIconId("emoji_key");
+
+    // Functional keys.
+    public static final ExpectedKey CAPSLOCK_MORE_KEY = key(" ", Constants.CODE_CAPSLOCK);
+    public static final ExpectedKey SHIFT_KEY = key(ICON_SHIFT, Constants.CODE_SHIFT);
+    public static final ExpectedKey DELETE_KEY = key(ICON_DELETE, Constants.CODE_DELETE);
+    public static final ExpectedKey SYMBOLS_KEY = key("?123", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+    public static final ExpectedKey SETTINGS_KEY = key(ICON_SETTINGS, Constants.CODE_SETTINGS);
+    public static final ExpectedKey ENTER_KEY = key(ICON_ENTER, Constants.CODE_ENTER);
+    public static final ExpectedKey EMOJI_KEY = key(ICON_EMOJI, Constants.CODE_EMOJI);
+
+    // Punctuation more keys for phone form factor.
+    public static final String[] PHONE_PUNCTUATION_MORE_KEYS = {
+            ";", "/", "(", ")", "#", "!", ",", "?",
+            "&", "%", "+", "\"", "-", ":", "'", "@"
+    };
+
+    // Punctuation more keys for tablet form factor.
+    public static final String[] TABLET_PUNCTUATION_MORE_KEYS = {
+            ";", "/", "(", ")", "#", "'", ",",
+            "&", "%", "+", "\"", "-", ":", "@"
+    };
+
+    private static ExpectedKeyboardBuilder toPhoneAlphabet(final ExpectedKeyboardBuilder builder) {
+        return builder
+                .addKeysOnTheLeftOfRow(3, key(SHIFT_KEY, CAPSLOCK_MORE_KEY))
+                .addKeysOnTheRightOfRow(3, DELETE_KEY)
+                .setLabelsOfRow(4, ",", " ", ".")
+                .setMoreKeysOf(",", SETTINGS_KEY)
+                .setMoreKeysOf(".", PHONE_PUNCTUATION_MORE_KEYS)
+                .addKeysOnTheLeftOfRow(4, SYMBOLS_KEY)
+                .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY));
+    }
+
+    // Helper method to create alphabet layout for tablet by adding special function keys except
+    // shift key.
+    public static ExpectedKeyboardBuilder toTabletAlphabetWithoutShiftKeys(
+            final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00BF: "¿" INVERTED QUESTION MARK
+                // U+00A1: "¡" INVERTED EXCLAMATION MARK
+                .addKeysOnTheRightOfRow(3,
+                        key("!", moreKey("\u00A1")), key("?", moreKey("\u00BF")))
+                .addKeysOnTheRightOfRow(1, DELETE_KEY)
+                .addKeysOnTheRightOfRow(2, ENTER_KEY)
+                .setLabelsOfRow(4, "/", " ", ",", ".")
+                .setMoreKeysOf(".", TABLET_PUNCTUATION_MORE_KEYS)
+                .addKeysOnTheLeftOfRow(4, SYMBOLS_KEY, SETTINGS_KEY)
+                .addKeysOnTheRightOfRow(4, EMOJI_KEY);
+    }
+
+    // Helper method to create alphabet layout by adding special function keys.
+    public static ExpectedKey[][] toCommonAlphabet(final ExpectedKey[][] common,
+            final boolean isPhone) {
+        final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(common);
+        if (isPhone) {
+            toPhoneAlphabet(builder);
+        } else {
+            toTabletAlphabetWithoutShiftKeys(builder);
+            builder.addKeysOnTheLeftOfRow(3, key(SHIFT_KEY, CAPSLOCK_MORE_KEY))
+                    .addKeysOnTheRightOfRow(3, key(SHIFT_KEY, CAPSLOCK_MORE_KEY));
+        }
+        return builder.build();
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java
new file mode 100644
index 0000000..427e7de
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java
@@ -0,0 +1,197 @@
+/*
+ * 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.layout.tests;
+
+import android.util.Log;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.KeyboardLayoutSet;
+import com.android.inputmethod.keyboard.KeyboardLayoutSetTestsBase;
+import com.android.inputmethod.keyboard.layout.AlphabetShifted;
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.expected.ActualKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.expected.LayoutBase;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.Arrays;
+import java.util.Locale;
+
+/**
+ * Base class for keyboard layout unit test.
+ */
+abstract class LayoutTestsBase extends KeyboardLayoutSetTestsBase {
+    private InputMethodSubtype mSubtype;
+    private String mLogTag;
+    private KeyboardLayoutSet mKeyboardLayoutSet;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mSubtype = getSubtype(getTestLocale(), getTestKeyboardLayout());
+        mLogTag = SubtypeLocaleUtils.getSubtypeNameForLogging(mSubtype) + "/"
+                + (isPhone() ? "phone" : "tablet");
+        mKeyboardLayoutSet = createKeyboardLayoutSet(mSubtype, null /* editorInfo */);
+    }
+
+    // Those helper methods have a lower case name to be readable when defining expected keyboard
+    // layouts.
+
+    // Helper method to create {@link ExpectedKey} object that has the label.
+    static ExpectedKey key(final String label, final ExpectedKey ... moreKeys) {
+        return LayoutBase.key(label, moreKeys);
+    }
+
+    // Helper method to create {@link ExpectedKey} object that has the label and the output text.
+    static ExpectedKey key(final String label, final String outputText,
+            final ExpectedKey ... moreKeys) {
+        return LayoutBase.key(label, outputText, moreKeys);
+    }
+
+    // Helper method to create {@link ExpectedKey} object for "more key" that has the label.
+    static ExpectedKey moreKey(final String label) {
+        return LayoutBase.moreKey(label);
+    }
+
+    // Helper method to create {@link ExpectedKey} object for "more key" that has the label and the
+    // output text.
+    static ExpectedKey moreKey(final String label, final String outputText) {
+        return LayoutBase.moreKey(label, outputText);
+    }
+
+    // Locale for testing subtype.
+    abstract Locale getTestLocale();
+
+    // Keyboard layout name for testing subtype.
+    abstract String getTestKeyboardLayout();
+
+    // Alphabet keyboard for testing subtype.
+    abstract ExpectedKey[][] getAlphabet(final boolean isPhone);
+
+    // Alphabet automatic shifted keyboard for testing subtype.
+    ExpectedKey[][] getAlphabetAutomaticShifted(final boolean isPhone) {
+        return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale());
+    }
+
+    // Alphabet manual shifted  keyboard for testing subtype.
+    ExpectedKey[][] getAlphabetManualShifted(final boolean isPhone) {
+        return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale());
+    }
+
+    // Alphabet shift locked keyboard for testing subtype.
+    ExpectedKey[][] getAlphabetShiftLocked(final boolean isPhone) {
+        return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale());
+    }
+
+    // Alphabet shift lock shifted keyboard for testing subtype.
+    ExpectedKey[][] getAlphabetShiftLockShifted(final boolean isPhone) {
+        return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale());
+    }
+
+    // Symbols keyboard for testing subtype.
+    ExpectedKey[][] getSymbols(final boolean isPhone) {
+        return Symbols.getSymbols(isPhone);
+    }
+
+    // Symbols shifted keyboard for testing subtype.
+    ExpectedKey[][] getSymbolsShifted(final boolean isPhone) {
+        return SymbolsShifted.getSymbolsShifted(isPhone);
+    }
+
+    // TODO: Add phone, phone symbols, number, number password layout tests.
+
+    public final void testAlphabet() {
+        final int elementId = KeyboardId.ELEMENT_ALPHABET;
+        doKeyboardTests(elementId, getAlphabet(isPhone()));
+    }
+
+    public final void testAlphabetAutomaticShifted() {
+        final int elementId = KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED;
+        doKeyboardTests(elementId, getAlphabetAutomaticShifted(isPhone()));
+    }
+
+    public final void testAlphabetManualShifted() {
+        final int elementId = KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED;
+        doKeyboardTests(elementId, getAlphabetManualShifted(isPhone()));
+    }
+
+    public final void testAlphabetShiftLocked() {
+        final int elementId = KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED;
+        doKeyboardTests(elementId, getAlphabetShiftLocked(isPhone()));
+    }
+
+    public final void testAlphabetShiftLockShifted() {
+        final int elementId = KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED;
+        doKeyboardTests(elementId, getAlphabetShiftLockShifted(isPhone()));
+    }
+
+    public final void testSymbols() {
+        final int elementId = KeyboardId.ELEMENT_SYMBOLS;
+        doKeyboardTests(elementId, getSymbols(isPhone()));
+    }
+
+    public final void testSymbolsShifted() {
+        final int elementId = KeyboardId.ELEMENT_SYMBOLS_SHIFTED;
+        doKeyboardTests(elementId, getSymbolsShifted(isPhone()));
+    }
+
+    // Comparing expected keyboard and actual keyboard.
+    private void doKeyboardTests(final int elementId, final ExpectedKey[][] expectedKeyboard) {
+        // Skip test if no keyboard is defined.
+        if (expectedKeyboard == null) {
+            return;
+        }
+        final String tag = mLogTag + "/" + KeyboardId.elementIdToName(elementId);
+        // Create actual keyboard object.
+        final Keyboard keyboard = mKeyboardLayoutSet.getKeyboard(elementId);
+        // Create actual keyboard to be compared with the expected keyboard.
+        final Key[][] actualKeyboard = ActualKeyboardBuilder.buildKeyboard(keyboard.getKeys());
+
+        // Dump human readable definition of expected/actual keyboards.
+        Log.d(tag, "expected=\n" + ExpectedKeyboardBuilder.toString(expectedKeyboard));
+        Log.d(tag, "actual  =\n" + ActualKeyboardBuilder.toString(actualKeyboard));
+        // Test both keyboards have the same number of rows.
+        assertEquals(tag + " labels"
+                + "\nexpected=" + Arrays.deepToString(expectedKeyboard)
+                + "\nactual  =" + ActualKeyboardBuilder.toString(actualKeyboard),
+                expectedKeyboard.length, actualKeyboard.length);
+        for (int r = 0; r < actualKeyboard.length; r++) {
+            final int row = r + 1;
+            // Test both keyboards' rows have the same number of columns.
+            assertEquals(tag + " labels row=" + row
+                    + "\nexpected=" + Arrays.toString(expectedKeyboard[r])
+                    + "\nactual  =" + ActualKeyboardBuilder.toString(actualKeyboard[r]),
+                    expectedKeyboard[r].length, actualKeyboard[r].length);
+            for (int c = 0; c < actualKeyboard[r].length; c++) {
+                final int column = c + 1;
+                final Key actualKey = actualKeyboard[r][c];
+                final ExpectedKey expectedKey = expectedKeyboard[r][c];
+                // Test both keyboards' keys have the same visual outlook and key output.
+                assertTrue(tag + " labels row,column=" + row + "," + column
+                        + "\nexpected=" + expectedKey
+                        + "\nactual  =" + ActualKeyboardBuilder.toString(actualKey),
+                        expectedKey.equalsTo(actualKey));
+            }
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java
new file mode 100644
index 0000000..0792a57
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java
@@ -0,0 +1,98 @@
+/*
+ * 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * en_US: English (United States)/qwerty
+ */
+@SmallTest
+public final class TestsEnglishUS extends LayoutTestsBase {
+    @Override
+    Locale getTestLocale() {
+        return new Locale("en", "US");
+    }
+
+    @Override
+    String getTestKeyboardLayout() {
+        return "qwerty";
+    }
+
+    @Override
+    ExpectedKey[][] getAlphabet(final boolean isPhone) {
+        final ExpectedKey[][] keyboard = Qwerty.getAlphabet(isPhone);
+        final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(keyboard);
+        setAccentedLetters(builder);
+        return builder.build();
+    }
+
+    static ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                .setMoreKeysOf("e", "3", "\u00E8", "\u00E9", "\u00EA", "\u00EB", "\u0113")
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "7", "\u00FB", "\u00FC", "\u00F9", "\u00FA", "\u016B")
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                .setMoreKeysOf("i", "8", "\u00EE", "\u00EF", "\u00ED", "\u012B", "\u00EC")
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                .setMoreKeysOf("o",
+                        "9", "\u00F4", "\u00F6", "\u00F2", "\u00F3", "\u0153", "\u00F8", "\u014D",
+                        "\u00F5")
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                .setMoreKeysOf("a",
+                        "\u00E0", "\u00E1", "\u00E2", "\u00E4", "\u00E6", "\u00E3", "\u00E5",
+                        "\u0101")
+                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+                .setMoreKeysOf("s", "\u00DF")
+                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+                .setMoreKeysOf("c", "\u00E7")
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                .setMoreKeysOf("n", "\u00F1");
+    }
+}
diff --git a/tools/Android.mk b/tools/Android.mk
index dc14033..91b2fbb 100644
--- a/tools/Android.mk
+++ b/tools/Android.mk
@@ -12,6 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Temporarily excluding dicttool
-#include $(call all-subdir-makefiles)
-include $(call all-named-subdir-makefiles, make-keyboard-text)
+include $(call all-subdir-makefiles)
diff --git a/tools/dicttool/Android.mk b/tools/dicttool/Android.mk
index b1dd7f6..c0a5562 100644
--- a/tools/dicttool/Android.mk
+++ b/tools/dicttool/Android.mk
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# HACK: Temporarily disable host tool build on Mac until the build system is ready for C++11.
+LATINIME_HOST_OSNAME := $(shell uname -s)
+ifneq ($(LATINIME_HOST_OSNAME), Darwin) # TODO: Remove this
+
 LATINIME_DICTTOOL_AOSP_LOCAL_PATH := $(call my-dir)
 LOCAL_PATH := $(LATINIME_DICTTOOL_AOSP_LOCAL_PATH)
 LATINIME_HOST_NATIVE_LIBNAME := liblatinime-aosp-dicttool-host
@@ -74,10 +78,14 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LATINIME_HOST_NATIVE_LIBNAME)
 LOCAL_JAR_MANIFEST := etc/manifest.txt
 LOCAL_MODULE := dicttool_aosp
+LOCAL_IS_HOST_MODULE := true
 
 include $(BUILD_HOST_JAVA_LIBRARY)
 include $(LOCAL_PATH)/etc/Android.mk
 
+endif # Darwin - TODO: Remove this
+
 # Clear our private variables
 LATINIME_DICTTOOL_AOSP_LOCAL_PATH :=
 LATINIME_LOCAL_DIR :=
+LATINIME_HOST_OSNAME :=
diff --git a/tools/dicttool/NativeLib.mk b/tools/dicttool/NativeLib.mk
index 26b6774..95f767d 100644
--- a/tools/dicttool/NativeLib.mk
+++ b/tools/dicttool/NativeLib.mk
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# HACK: Temporarily disable host tool build on Mac until the build system is ready for C++11.
+LATINIME_HOST_OSNAME := $(shell uname -s)
+ifneq ($(LATINIME_HOST_OSNAME), Darwin) # TODO: Remove this
+
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -49,9 +53,13 @@
     $(addprefix $(LATINIME_NATIVE_SRC_DIR)/, $(LATIN_IME_CORE_SRC_FILES))
 
 LOCAL_MODULE := $(LATINIME_HOST_NATIVE_LIBNAME)
+LOCAL_IS_HOST_MODULE := true
 
 include $(BUILD_HOST_SHARED_LIBRARY)
 
+endif # Darwin - TODO: Remove this
+
 # Clear our private variables
 include $(LOCAL_PATH)/$(LATINIME_NATIVE_JNI_DIR)/CleanupNativeFileList.mk
 LATINIME_DIR_RELATIVE_TO_DICTTOOL := ../..
+LATINIME_HOST_OSNAME :=