Merge "Fix SuggestTests"
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 1f7736d..e6f036d 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -161,6 +161,8 @@
 
     <!-- Generic subtype label -->
     <string name="subtype_generic">%s</string>
+    <!-- Description for generic QWERTY keyboard subtype -->
+    <string name="subtype_generic_qwerty">%s (QWERTY)</string>
 
     <!-- dictionary pack package name /settings activity (for shared prefs and settings) -->
     <string name="dictionary_pack_package_name">com.google.android.inputmethod.latin.dictionarypack</string>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index d860a1b..f7d8b45 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -335,8 +335,6 @@
     <!-- Title of the item to change the keyboard theme [CHAR LIMIT=20]-->
     <string name="keyboard_layout">Keyboard theme</string>
 
-    <!-- Description for German QWERTY keyboard subtype [CHAR LIMIT=22] -->
-    <string name="subtype_de_qwerty">German QWERTY</string>
     <!-- Description for English (United Kingdom) keyboard subtype [CHAR LIMIT=22] -->
     <string name="subtype_en_GB">English (UK)</string>
     <!-- Description for English (United States) keyboard subtype [CHAR LIMIT=22] -->
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index a3b1d58..6c82736 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -71,7 +71,7 @@
             android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
-            android:label="@string/subtype_de_qwerty"
+            android:label="@string/subtype_generic_qwerty"
             android:imeSubtypeLocale="de"
             android:imeSubtypeMode="keyboard"
             android:imeSubtypeExtraValue="AsciiCapable,KeyboardLocale=de_ZZ,SupportTouchPositionCorrection"
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 3433cd4..4d2aeec 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -806,7 +806,7 @@
         return bounds.width();
     }
 
-    // Layout local language name and left and right arrow on spacebar.
+    // Layout locale language name on spacebar.
     private static String layoutSpacebar(Paint paint, Locale locale, int width,
             float origTextSize) {
         final Rect bounds = new Rect();
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 4211182..f577816 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -46,8 +46,8 @@
     private static boolean DBG = LatinImeLogger.sDBG;
     private static final String TAG = SubtypeSwitcher.class.getSimpleName();
 
+    public static final String KEYBOARD_MODE = "keyboard";
     private static final char LOCALE_SEPARATER = '_';
-    private static final String KEYBOARD_MODE = "keyboard";
     private static final String VOICE_MODE = "voice";
     private static final String SUBTYPE_EXTRAVALUE_REQUIRE_NETWORK_CONNECTIVITY =
             "requireNetworkConnectivity";
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 3814843..8e0cfa1 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -154,10 +154,21 @@
             }
         }
 
-        return filteredImisCount > 1
-        // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
-        // input method subtype (The current IME should be LatinIME.)
-                || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
+        if (filteredImisCount > 1) {
+            return true;
+        }
+        final List<InputMethodSubtypeCompatWrapper> subtypes =
+                imm.getEnabledInputMethodSubtypeList(null, true);
+        int keyboardCount = 0;
+        // imm.getEnabledInputMethodSubtypeList(null, true) will return the current IME's
+        // both explicitly and implicitly enabled input method subtype.
+        // (The current IME should be LatinIME.)
+        for (InputMethodSubtypeCompatWrapper subtype : subtypes) {
+            if (SubtypeSwitcher.KEYBOARD_MODE.equals(subtype.getMode())) {
+                ++keyboardCount;
+            }
+        }
+        return keyboardCount > 1;
     }
 
     public static String getInputMethodId(InputMethodManagerCompatWrapper imm, String packageName) {
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 71a893c..f2878ee 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -51,7 +51,7 @@
     PROF_START(66);
     const char *sourceDirChars = env->GetStringUTFChars(sourceDir, 0);
     if (sourceDirChars == 0) {
-        LOGE("DICT: Can't get sourceDir string");
+        AKLOGE("DICT: Can't get sourceDir string");
         return 0;
     }
     int fd = 0;
@@ -61,7 +61,7 @@
     /* mmap version */
     fd = open(sourceDirChars, O_RDONLY);
     if (fd < 0) {
-        LOGE("DICT: Can't open sourceDir. sourceDirChars=%s errno=%d", sourceDirChars, errno);
+        AKLOGE("DICT: Can't open sourceDir. sourceDirChars=%s errno=%d", sourceDirChars, errno);
         return 0;
     }
     int pagesize = getpagesize();
@@ -70,7 +70,7 @@
     int adjDictSize = dictSize + adjust;
     dictBuf = mmap(0, sizeof(char) * adjDictSize, PROT_READ, MAP_PRIVATE, fd, adjDictOffset);
     if (dictBuf == MAP_FAILED) {
-        LOGE("DICT: Can't mmap dictionary. errno=%d", errno);
+        AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno);
         return 0;
     }
     dictBuf = (void *)((char *)dictBuf + adjust);
@@ -79,39 +79,39 @@
     FILE *file = 0;
     file = fopen(sourceDirChars, "rb");
     if (file == 0) {
-        LOGE("DICT: Can't fopen sourceDir. sourceDirChars=%s errno=%d", sourceDirChars, errno);
+        AKLOGE("DICT: Can't fopen sourceDir. sourceDirChars=%s errno=%d", sourceDirChars, errno);
         return 0;
     }
     dictBuf = malloc(sizeof(char) * dictSize);
     if (!dictBuf) {
-        LOGE("DICT: Can't allocate memory region for dictionary. errno=%d", errno);
+        AKLOGE("DICT: Can't allocate memory region for dictionary. errno=%d", errno);
         return 0;
     }
     int ret = fseek(file, (long)dictOffset, SEEK_SET);
     if (ret != 0) {
-        LOGE("DICT: Failure in fseek. ret=%d errno=%d", ret, errno);
+        AKLOGE("DICT: Failure in fseek. ret=%d errno=%d", ret, errno);
         return 0;
     }
     ret = fread(dictBuf, sizeof(char) * dictSize, 1, file);
     if (ret != 1) {
-        LOGE("DICT: Failure in fread. ret=%d errno=%d", ret, errno);
+        AKLOGE("DICT: Failure in fread. ret=%d errno=%d", ret, errno);
         return 0;
     }
     ret = fclose(file);
     if (ret != 0) {
-        LOGE("DICT: Failure in fclose. ret=%d errno=%d", ret, errno);
+        AKLOGE("DICT: Failure in fclose. ret=%d errno=%d", ret, errno);
         return 0;
     }
 #endif // USE_MMAP_FOR_DICTIONARY
     env->ReleaseStringUTFChars(sourceDir, sourceDirChars);
 
     if (!dictBuf) {
-        LOGE("DICT: dictBuf is null");
+        AKLOGE("DICT: dictBuf is null");
         return 0;
     }
     Dictionary *dictionary = 0;
     if (BinaryFormat::UNKNOWN_FORMAT == BinaryFormat::detectFormat((uint8_t*)dictBuf)) {
-        LOGE("DICT: dictionary format is unknown, bad magic number");
+        AKLOGE("DICT: dictionary format is unknown, bad magic number");
 #ifdef USE_MMAP_FOR_DICTIONARY
         releaseDictBuf(((char*)dictBuf) - adjust, adjDictSize, fd);
 #else // USE_MMAP_FOR_DICTIONARY
@@ -230,11 +230,11 @@
 #ifdef USE_MMAP_FOR_DICTIONARY
     int ret = munmap(dictBuf, length);
     if (ret != 0) {
-        LOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
+        AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
     }
     ret = close(fd);
     if (ret != 0) {
-        LOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
+        AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
     }
 #else // USE_MMAP_FOR_DICTIONARY
     free(dictBuf);
diff --git a/native/jni/jni_common.cpp b/native/jni/jni_common.cpp
index 958abfd..85d2683 100644
--- a/native/jni/jni_common.cpp
+++ b/native/jni/jni_common.cpp
@@ -36,18 +36,18 @@
     jint result = -1;
 
     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
-        LOGE("ERROR: GetEnv failed");
+        AKLOGE("ERROR: GetEnv failed");
         goto bail;
     }
     assert(env != 0);
 
     if (!register_BinaryDictionary(env)) {
-        LOGE("ERROR: BinaryDictionary native registration failed");
+        AKLOGE("ERROR: BinaryDictionary native registration failed");
         goto bail;
     }
 
     if (!register_ProximityInfo(env)) {
-        LOGE("ERROR: ProximityInfo native registration failed");
+        AKLOGE("ERROR: ProximityInfo native registration failed");
         goto bail;
     }
 
@@ -64,11 +64,11 @@
         int numMethods) {
     jclass clazz = env->FindClass(className);
     if (clazz == 0) {
-        LOGE("Native registration unable to find class '%s'", className);
+        AKLOGE("Native registration unable to find class '%s'", className);
         return JNI_FALSE;
     }
     if (env->RegisterNatives(clazz, methods, numMethods) < 0) {
-        LOGE("RegisterNatives failed for '%s'", className);
+        AKLOGE("RegisterNatives failed for '%s'", className);
         env->DeleteLocalRef(clazz);
         return JNI_FALSE;
     }
diff --git a/native/src/bigram_dictionary.cpp b/native/src/bigram_dictionary.cpp
index c340c6c..db7734b 100644
--- a/native/src/bigram_dictionary.cpp
+++ b/native/src/bigram_dictionary.cpp
@@ -32,8 +32,8 @@
     MAX_ALTERNATIVES(maxAlternatives), IS_LATEST_DICT_VERSION(isLatestDictVersion),
     HAS_BIGRAM(hasBigram), mParentDictionary(parentDictionary) {
     if (DEBUG_DICT) {
-        LOGI("BigramDictionary - constructor");
-        LOGI("Has Bigram : %d", hasBigram);
+        AKLOGI("BigramDictionary - constructor");
+        AKLOGI("Has Bigram : %d", hasBigram);
     }
 }
 
@@ -46,7 +46,7 @@
 #ifdef FLAG_DBG
         char s[length + 1];
         for (int i = 0; i <= length; i++) s[i] = word[i];
-        LOGI("Bigram: Found word = %s, freq = %d :", s, frequency);
+        AKLOGI("Bigram: Found word = %s, freq = %d :", s, frequency);
 #endif
     }
 
@@ -60,7 +60,7 @@
         insertAt++;
     }
     if (DEBUG_DICT) {
-        LOGI("Bigram: InsertAt -> %d maxBigrams: %d", insertAt, mMaxBigrams);
+        AKLOGI("Bigram: InsertAt -> %d maxBigrams: %d", insertAt, mMaxBigrams);
     }
     if (insertAt < mMaxBigrams) {
         memmove((char*) mBigramFreq + (insertAt + 1) * sizeof(mBigramFreq[0]),
@@ -76,7 +76,7 @@
         }
         *dest = 0; // NULL terminate
         if (DEBUG_DICT) {
-            LOGI("Bigram: Added word at %d", insertAt);
+            AKLOGI("Bigram: Added word at %d", insertAt);
         }
         return true;
     }
diff --git a/native/src/correction.cpp b/native/src/correction.cpp
index dc31bfa..c40f94b 100644
--- a/native/src/correction.cpp
+++ b/native/src/correction.cpp
@@ -42,7 +42,7 @@
 inline static void dumpEditDistance10ForDebug(int *editDistanceTable, const int inputLength,
         const int outputLength) {
     if (DEBUG_DICT) {
-        LOGI("EditDistanceTable");
+        AKLOGI("EditDistanceTable");
         for (int i = 0; i <= 10; ++i) {
             int c[11];
             for (int j = 0; j <= 10; ++j) {
@@ -52,7 +52,7 @@
                     c[j] = -1;
                 }
             }
-            LOGI("[ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d ]",
+            AKLOGI("[ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d ]",
                     c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10]);
         }
     }
@@ -84,7 +84,7 @@
 inline static int getCurrentEditDistance(
         int *editDistanceTable, const int inputLength, const int outputLength) {
     if (DEBUG_DICT) {
-        LOGI("getCurrentEditDistance %d, %d", inputLength, outputLength);
+        AKLOGI("getCurrentEditDistance %d, %d", inputLength, outputLength);
     }
     return editDistanceTable[(inputLength + 1) * (outputLength + 1) - 1];
 }
@@ -378,7 +378,7 @@
             --mTransposedCount;
             if (DEBUG_CORRECTION) {
                 DUMP_WORD(mWord, mOutputIndex);
-                LOGI("UNRELATED(0): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount,
+                AKLOGI("UNRELATED(0): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount,
                         mTransposedCount, mExcessiveCount, c);
             }
             return UNRELATED;
@@ -404,7 +404,7 @@
                 && isEquivalentChar(mProximityInfo->getMatchedProximityId(
                         mInputIndex, mWord[mOutputIndex - 1], false))) {
             if (DEBUG_CORRECTION) {
-                LOGI("CONVERSION p->e %c", mWord[mOutputIndex - 1]);
+                AKLOGI("CONVERSION p->e %c", mWord[mOutputIndex - 1]);
             }
             // Conversion p->e
             // Example:
@@ -481,7 +481,7 @@
         } else {
             if (DEBUG_CORRECTION) {
                 DUMP_WORD(mWord, mOutputIndex);
-                LOGI("UNRELATED(1): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount,
+                AKLOGI("UNRELATED(1): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount,
                         mTransposedCount, mExcessiveCount, c);
             }
             return UNRELATED;
@@ -534,7 +534,7 @@
         mTerminalOutputIndex = mOutputIndex - 1;
         if (DEBUG_CORRECTION) {
             DUMP_WORD(mWord, mOutputIndex);
-            LOGI("ONTERMINAL(1): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount,
+            AKLOGI("ONTERMINAL(1): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount,
                     mTransposedCount, mExcessiveCount, c);
         }
         return ON_TERMINAL;
@@ -703,7 +703,7 @@
                 / (10 * inputLength
                         - WORDS_WITH_MISSING_CHARACTER_DEMOTION_START_POS_10X + 10);
         if (DEBUG_DICT_FULL) {
-            LOGI("Demotion rate for missing character is %d.", demotionRate);
+            AKLOGI("Demotion rate for missing character is %d.", demotionRate);
         }
         multiplyRate(demotionRate, &finalFreq);
     }
@@ -717,7 +717,7 @@
         multiplyRate(WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE, &finalFreq);
         if (!lastCharExceeded && !proximityInfo->existsAdjacentProximityChars(excessivePos)) {
             if (DEBUG_CORRECTION_FREQ) {
-                LOGI("Double excessive demotion");
+                AKLOGI("Double excessive demotion");
             }
             // If an excessive character is not adjacent to the left char or the right char,
             // we will demote this word.
@@ -767,7 +767,7 @@
         for (int i = 0; i < adjustedProximityMatchedCount; ++i) {
             // A word with proximity corrections
             if (DEBUG_DICT_FULL) {
-                LOGI("Found a proximity correction.");
+                AKLOGI("Found a proximity correction.");
             }
             multiplyIntCapped(typedLetterMultiplier, &finalFreq);
             multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
@@ -828,12 +828,12 @@
     }
 
     if (DEBUG_DICT_FULL) {
-        LOGI("calc: %d, %d", outputIndex, sameLength);
+        AKLOGI("calc: %d, %d", outputIndex, sameLength);
     }
 
     if (DEBUG_CORRECTION_FREQ) {
         DUMP_WORD(correction->mWord, outputIndex + 1);
-        LOGI("FinalFreq: [P%d, S%d, T%d, E%d] %d, %d, %d, %d, %d", proximityMatchedCount,
+        AKLOGI("FinalFreq: [P%d, S%d, T%d, E%d] %d, %d, %d, %d, %d", proximityMatchedCount,
                 skippedCount, transposedCount, excessiveCount, lastCharExceeded, sameLength,
                 quoteDiffCount, ed, finalFreq);
     }
@@ -874,7 +874,8 @@
             firstCapitalizedWordDemotion ^ secondCapitalizedWordDemotion;
 
     if (DEBUG_DICT_FULL) {
-        LOGI("Two words: %c, %c, %d", word[0], word[firstWordLength + 1], capitalizedWordDemotion);
+        AKLOGI("Two words: %c, %c, %d",
+                word[0], word[firstWordLength + 1], capitalizedWordDemotion);
     }
 
     if (firstWordLength == 0 || secondWordLength == 0) {
@@ -919,7 +920,7 @@
     if (isSpaceProximity) {
         // A word pair with one space proximity correction
         if (DEBUG_DICT) {
-            LOGI("Found a word pair with space proximity correction.");
+            AKLOGI("Found a word pair with space proximity correction.");
         }
         multiplyIntCapped(typedLetterMultiplier, &totalFreq);
         multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &totalFreq);
@@ -965,10 +966,10 @@
     }
 
     if (DEBUG_EDIT_DISTANCE) {
-        LOGI("IN = %d, OUT = %d", beforeLength, afterLength);
+        AKLOGI("IN = %d, OUT = %d", beforeLength, afterLength);
         for (int i = 0; i < li; ++i) {
             for (int j = 0; j < lo; ++j) {
-                LOGI("EDIT[%d][%d], %d", i, j, dp[i * lo + j]);
+                AKLOGI("EDIT[%d][%d], %d", i, j, dp[i * lo + j]);
             }
         }
     }
diff --git a/native/src/debug.h b/native/src/debug.h
index 38b2f10..b13052c 100644
--- a/native/src/debug.h
+++ b/native/src/debug.h
@@ -42,7 +42,7 @@
 static inline void LOGI_S16(unsigned short* string, const unsigned int length) {
     unsigned char tmp_buffer[length];
     convertToUnibyteString(string, tmp_buffer, length);
-    LOGI(">> %s", tmp_buffer);
+    AKLOGI(">> %s", tmp_buffer);
     // The log facility is throwing out log that comes too fast. The following
     // is a dirty way of slowing down processing so that we can see all log.
     // TODO : refactor this in a blocking log or something.
@@ -53,7 +53,7 @@
         unsigned char c) {
     unsigned char tmp_buffer[length+1];
     convertToUnibyteStringAndReplaceLastChar(string, tmp_buffer, length, c);
-    LOGI(">> %s", tmp_buffer);
+    AKLOGI(">> %s", tmp_buffer);
     // Likewise
     // usleep(10);
 }
@@ -64,7 +64,7 @@
     buf[codesSize] = 0;
     while (--codesSize >= 0)
         buf[codesSize] = (unsigned char)codes[codesSize * MAX_PROXIMITY_CHARS];
-    LOGI("%s, WORD = %s", tag, buf);
+    AKLOGI("%s, WORD = %s", tag, buf);
 
     free(buf);
 }
diff --git a/native/src/defines.h b/native/src/defines.h
index d636e51..01ef656 100644
--- a/native/src/defines.h
+++ b/native/src/defines.h
@@ -20,15 +20,18 @@
 
 #if defined(FLAG_DO_PROFILE) || defined(FLAG_DBG)
 #include <cutils/log.h>
+#define AKLOGE ALOGE
+#define AKLOGI ALOGI
 #else
-#define LOGE(fmt, ...)
-#define LOGI(fmt, ...)
+#define AKLOGE(fmt, ...)
+#define AKLOGI(fmt, ...)
 #endif
 
 #ifdef FLAG_DO_PROFILE
 // Profiler
 #include <cutils/log.h>
 #include <time.h>
+
 #define PROF_BUF_SIZE 100
 static double profile_buf[PROF_BUF_SIZE];
 static double profile_old[PROF_BUF_SIZE];
@@ -42,8 +45,8 @@
 #define PROF_CLOSE               do { PROF_END(PROF_BUF_SIZE - 1); PROF_OUTALL; } while(0)
 #define PROF_END(prof_buf_id)    profile_buf[prof_buf_id] += ((clock()) - profile_old[prof_buf_id])
 #define PROF_CLOCKOUT(prof_buf_id) \
-        LOGI("%s : clock is %f", __FUNCTION__, (clock() - profile_old[prof_buf_id]))
-#define PROF_OUTALL              do { LOGI("--- %s ---", __FUNCTION__); prof_out(); } while(0)
+        AKLOGI("%s : clock is %f", __FUNCTION__, (clock() - profile_old[prof_buf_id]))
+#define PROF_OUTALL              do { AKLOGI("--- %s ---", __FUNCTION__); prof_out(); } while(0)
 
 static void prof_reset(void) {
     for (int i = 0; i < PROF_BUF_SIZE; ++i) {
@@ -55,9 +58,9 @@
 
 static void prof_out(void) {
     if (profile_counter[PROF_BUF_SIZE - 1] != 1) {
-        LOGI("Error: You must call PROF_OPEN before PROF_CLOSE.");
+        AKLOGI("Error: You must call PROF_OPEN before PROF_CLOSE.");
     }
-    LOGI("Total time is %6.3f ms.",
+    AKLOGI("Total time is %6.3f ms.",
             profile_buf[PROF_BUF_SIZE - 1] * 1000 / (double)CLOCKS_PER_SEC);
     double all = 0;
     for (int i = 0; i < PROF_BUF_SIZE - 1; ++i) {
@@ -66,7 +69,7 @@
     if (all == 0) all = 1;
     for (int i = 0; i < PROF_BUF_SIZE - 1; ++i) {
         if (profile_buf[i] != 0) {
-            LOGI("(%d): Used %4.2f%%, %8.4f ms. Called %d times.",
+            AKLOGI("(%d): Used %4.2f%%, %8.4f ms. Called %d times.",
                     i, (profile_buf[i] * 100 / all),
                     profile_buf[i] * 1000 / (double)CLOCKS_PER_SEC, profile_counter[i]);
         }
@@ -112,7 +115,7 @@
         charBuf[i] = word[i];
     }
     charBuf[length] = 0;
-    LOGI("[ %s ]", charBuf);
+    AKLOGI("[ %s ]", charBuf);
 }
 
 #else // FLAG_DBG
@@ -205,6 +208,7 @@
 // Word limit for sub queues used in WordsPriorityQueuePool.  Sub queues are temporary queues used
 // for better performance.
 #define SUB_QUEUE_MAX_WORDS 5
+#define SUB_QUEUE_MAX_COUNT 10
 
 #define MAX_DEPTH_MULTIPLIER 3
 
diff --git a/native/src/dictionary.cpp b/native/src/dictionary.cpp
index e3673d4..822c215 100644
--- a/native/src/dictionary.cpp
+++ b/native/src/dictionary.cpp
@@ -33,9 +33,9 @@
     IS_LATEST_DICT_VERSION((((unsigned char*) dict)[0] & 0xFF) >= DICTIONARY_VERSION_MIN) {
     if (DEBUG_DICT) {
         if (MAX_WORD_LENGTH_INTERNAL < maxWordLength) {
-            LOGI("Max word length (%d) is greater than %d",
+            AKLOGI("Max word length (%d) is greater than %d",
                     maxWordLength, MAX_WORD_LENGTH_INTERNAL);
-            LOGI("IN NATIVE SUGGEST Version: %d", (mDict[0] & 0xFF));
+            AKLOGI("IN NATIVE SUGGEST Version: %d", (mDict[0] & 0xFF));
         }
     }
     mCorrection = new Correction(typedLetterMultiplier, fullWordMultiplier);
diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp
index 95e3526..b91957c 100644
--- a/native/src/proximity_info.cpp
+++ b/native/src/proximity_info.cpp
@@ -52,7 +52,7 @@
     const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE;
     mProximityCharsArray = new uint32_t[proximityGridLength];
     if (DEBUG_PROXIMITY_INFO) {
-        LOGI("Create proximity info array %d", proximityGridLength);
+        AKLOGI("Create proximity info array %d", proximityGridLength);
     }
     memcpy(mProximityCharsArray, proximityCharsArray,
             proximityGridLength * sizeof(mProximityCharsArray[0]));
@@ -102,7 +102,7 @@
 bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
     if (x < 0 || y < 0) {
         if (DEBUG_DICT) {
-            LOGI("HasSpaceProximity: Illegal coordinates (%d, %d)", x, y);
+            AKLOGI("HasSpaceProximity: Illegal coordinates (%d, %d)", x, y);
             assert(false);
         }
         return false;
@@ -110,11 +110,11 @@
 
     const int startIndex = getStartIndexFromCoordinates(x, y);
     if (DEBUG_PROXIMITY_INFO) {
-        LOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y);
+        AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y);
     }
     for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
         if (DEBUG_PROXIMITY_INFO) {
-            LOGI("Index: %d", mProximityCharsArray[startIndex + i]);
+            AKLOGI("Index: %d", mProximityCharsArray[startIndex + i]);
         }
         if (mProximityCharsArray[startIndex + i] == KEYCODE_SPACE) {
             return true;
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index e95e03c..a6ecc2d 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -47,7 +47,7 @@
     BYTES_IN_ONE_CHAR(MAX_PROXIMITY_CHARS * sizeof(int)),
     MAX_UMLAUT_SEARCH_DEPTH(DEFAULT_MAX_UMLAUT_SEARCH_DEPTH) {
     if (DEBUG_DICT) {
-        LOGI("UnigramDictionary - constructor");
+        AKLOGI("UnigramDictionary - constructor");
     }
 }
 
@@ -163,14 +163,14 @@
             queuePool->getMasterQueue()->outputSuggestions(frequencies, outWords);
 
     if (DEBUG_DICT) {
-        LOGI("Returning %d words", suggestedWordsCount);
+        AKLOGI("Returning %d words", suggestedWordsCount);
         /// Print the returned words
         for (int j = 0; j < suggestedWordsCount; ++j) {
 #ifdef FLAG_DBG
             short unsigned int* w = outWords + j * MAX_WORD_LENGTH;
             char s[MAX_WORD_LENGTH];
             for (int i = 0; i <= MAX_WORD_LENGTH; i++) s[i] = w[i];
-            LOGI("%s %i", s, frequencies[j]);
+            AKLOGI("%s %i", s, frequencies[j]);
 #endif
         }
     }
@@ -213,7 +213,7 @@
             && inputLength >= MIN_USER_TYPED_LENGTH_FOR_MISSING_SPACE_SUGGESTION) {
         for (int i = 1; i < inputLength; ++i) {
             if (DEBUG_DICT) {
-                LOGI("--- Suggest missing space characters %d", i);
+                AKLOGI("--- Suggest missing space characters %d", i);
             }
             getMissingSpaceWords(proximityInfo, xcoordinates, ycoordinates, codes,
                     useFullEditDistance, inputLength, i, correction, queuePool);
@@ -226,12 +226,12 @@
         // The first and last "mistyped spaces" are taken care of by excessive character handling
         for (int i = 1; i < inputLength - 1; ++i) {
             if (DEBUG_DICT) {
-                LOGI("--- Suggest words with proximity space %d", i);
+                AKLOGI("--- Suggest words with proximity space %d", i);
             }
             const int x = xcoordinates[i];
             const int y = ycoordinates[i];
             if (DEBUG_PROXIMITY_INFO) {
-                LOGI("Input[%d] x = %d, y = %d, has space proximity = %d",
+                AKLOGI("Input[%d] x = %d, y = %d, has space proximity = %d",
                         i, x, y, proximityInfo->hasSpaceProximity(x, y));
             }
             if (proximityInfo->hasSpaceProximity(x, y)) {
@@ -247,7 +247,7 @@
         const int *yCoordinates, const int *codes, const int inputLength,
         WordsPriorityQueue *queue, Correction *correction) {
     if (DEBUG_DICT) {
-        LOGI("initSuggest");
+        AKLOGI("initSuggest");
     }
     proximityInfo->setInputParams(codes, inputLength, xCoordinates, yCoordinates);
     if (queue) {
@@ -390,7 +390,7 @@
     const int firstFreq = getMostFrequentWordLike(
             firstWordStartPos, firstWordLength, proximityInfo, mWord);
     if (DEBUG_DICT) {
-        LOGI("First freq: %d", firstFreq);
+        AKLOGI("First freq: %d", firstFreq);
     }
     if (firstFreq <= 0) return;
 
@@ -401,7 +401,7 @@
     const int secondFreq = getMostFrequentWordLike(
             secondWordStartPos, secondWordLength, proximityInfo, mWord);
     if (DEBUG_DICT) {
-        LOGI("Second  freq:  %d", secondFreq);
+        AKLOGI("Second  freq:  %d", secondFreq);
     }
     if (secondFreq <= 0) return;
 
@@ -419,7 +419,7 @@
             useFullEditDistance, false /* doAutoCompletion */, MAX_ERRORS_FOR_TWO_WORDS);
     const int pairFreq = correction->getFreqForSplitTwoWords(firstFreq, secondFreq, word);
     if (DEBUG_DICT) {
-        LOGI("Split two words:  %d, %d, %d, %d", firstFreq, secondFreq, pairFreq, inputLength);
+        AKLOGI("Split two words:  %d, %d, %d, %d", firstFreq, secondFreq, pairFreq, inputLength);
     }
     addWord(word, newWordLength, pairFreq, masterQueue);
     return;
@@ -690,7 +690,7 @@
             *nextSiblingPosition =
                     BinaryFormat::skipChildrenPosAndAttributes(DICT_ROOT, flags, pos);
             if (DEBUG_DICT_FULL) {
-                LOGI("Traversing was pruned.");
+                AKLOGI("Traversing was pruned.");
             }
             return false;
         }
diff --git a/native/src/words_priority_queue.h b/native/src/words_priority_queue.h
index 84f2523..ce5d2ce 100644
--- a/native/src/words_priority_queue.h
+++ b/native/src/words_priority_queue.h
@@ -48,6 +48,7 @@
             mSuggestedWords[i].mUsed = false;
         }
     }
+
     ~WordsPriorityQueue() {
         delete[] mSuggestedWords;
     }
@@ -70,11 +71,11 @@
             sw->setParams(score, word, wordLength);
         }
         if (sw == 0) {
-            LOGE("SuggestedWord is accidentally null.");
+            AKLOGE("SuggestedWord is accidentally null.");
             return;
         }
         if (DEBUG_WORDS_PRIORITY_QUEUE) {
-            LOGI("Push word. %d, %d", score, wordLength);
+            AKLOGI("Push word. %d, %d", score, wordLength);
             DUMP_WORD(word, wordLength);
         }
         mSuggestions.push(sw);
@@ -93,7 +94,7 @@
         while (!mSuggestions.empty() && index >= 0) {
             SuggestedWord* sw = mSuggestions.top();
             if (DEBUG_WORDS_PRIORITY_QUEUE) {
-                LOGI("dump word. %d", sw->mScore);
+                AKLOGI("dump word. %d", sw->mScore);
                 DUMP_WORD(sw->mWord, sw->mWordLength);
             }
             const unsigned int wordLength = sw->mWordLength;
@@ -119,7 +120,7 @@
         while (!mSuggestions.empty()) {
             SuggestedWord* sw = mSuggestions.top();
             if (DEBUG_WORDS_PRIORITY_QUEUE) {
-                LOGI("Clear word. %d", sw->mScore);
+                AKLOGI("Clear word. %d", sw->mScore);
                 DUMP_WORD(sw->mWord, sw->mWordLength);
             }
             sw->mUsed = false;
diff --git a/native/src/words_priority_queue_pool.h b/native/src/words_priority_queue_pool.h
index 3862976..bf9619e 100644
--- a/native/src/words_priority_queue_pool.h
+++ b/native/src/words_priority_queue_pool.h
@@ -17,6 +17,8 @@
 #ifndef LATINIME_WORDS_PRIORITY_QUEUE_POOL_H
 #define LATINIME_WORDS_PRIORITY_QUEUE_POOL_H
 
+#include <assert.h>
+#include <new>
 #include "words_priority_queue.h"
 
 namespace latinime {
@@ -24,30 +26,45 @@
 class WordsPriorityQueuePool {
  public:
     WordsPriorityQueuePool(int mainQueueMaxWords, int subQueueMaxWords, int maxWordLength) {
-        mMasterQueue = new WordsPriorityQueue(mainQueueMaxWords, maxWordLength);
-        mSubQueue1 = new WordsPriorityQueue(subQueueMaxWords, maxWordLength);
-        mSubQueue2 = new WordsPriorityQueue(subQueueMaxWords, maxWordLength);
+        mMasterQueue = new(mMasterQueueBuf) WordsPriorityQueue(mainQueueMaxWords, maxWordLength);
+        for (int i = 0, subQueueBufOffset = 0; i < SUB_QUEUE_MAX_COUNT;
+                ++i, subQueueBufOffset += sizeof(WordsPriorityQueue)) {
+            mSubQueues1[i] = new(mSubQueueBuf1 + subQueueBufOffset)
+                    WordsPriorityQueue(subQueueMaxWords, maxWordLength);
+            mSubQueues2[i] = new(mSubQueueBuf2 + subQueueBufOffset)
+                    WordsPriorityQueue(subQueueMaxWords, maxWordLength);
+        }
     }
 
-    ~WordsPriorityQueuePool() {
-        delete mMasterQueue;
+    virtual ~WordsPriorityQueuePool() {
     }
 
     WordsPriorityQueue* getMasterQueue() {
         return mMasterQueue;
     }
+
     // TODO: Come up with more generic pool
-    WordsPriorityQueue* getSubQueue1() {
-        return mSubQueue1;
+    WordsPriorityQueue* getSubQueue1(const int id) {
+        if (DEBUG_WORDS_PRIORITY_QUEUE) {
+            assert(id >= 0 && id < SUB_QUEUE_MAX_COUNT);
+        }
+        return mSubQueues1[id];
     }
-    WordsPriorityQueue* getSubQueue2() {
-        return mSubQueue2;
+
+    WordsPriorityQueue* getSubQueue2(const int id) {
+        if (DEBUG_WORDS_PRIORITY_QUEUE) {
+            assert(id >= 0 && id < SUB_QUEUE_MAX_COUNT);
+        }
+        return mSubQueues2[id];
     }
 
  private:
-    WordsPriorityQueue *mMasterQueue;
-    WordsPriorityQueue *mSubQueue1;
-    WordsPriorityQueue *mSubQueue2;
+    WordsPriorityQueue* mMasterQueue;
+    WordsPriorityQueue* mSubQueues1[SUB_QUEUE_MAX_COUNT];
+    WordsPriorityQueue* mSubQueues2[SUB_QUEUE_MAX_COUNT];
+    char mMasterQueueBuf[sizeof(WordsPriorityQueue)];
+    char mSubQueueBuf1[SUB_QUEUE_MAX_COUNT * sizeof(WordsPriorityQueue)];
+    char mSubQueueBuf2[SUB_QUEUE_MAX_COUNT * sizeof(WordsPriorityQueue)];
 };
 }
 
diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
index fec3e8e..7925d1a 100644
--- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
+++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
@@ -16,10 +16,7 @@
 
 package com.android.inputmethod.latin;
 
-import com.android.inputmethod.latin.LocaleUtils;
-
 import android.content.Context;
-import android.content.res.Resources;
 import android.test.AndroidTestCase;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -30,24 +27,22 @@
 import java.util.Locale;
 
 public class SubtypeLocaleTests extends AndroidTestCase {
-    private static final String PACKAGE = LatinIME.class.getPackage().getName();
-
-    private Resources mRes;
-    private List<InputMethodSubtype> mKeyboardSubtypes = new ArrayList<InputMethodSubtype>();
+    private List<InputMethodSubtype> mKeyboardSubtypes;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
         final Context context = getContext();
-        mRes = context.getResources();
+        final String packageName = context.getApplicationInfo().packageName;
 
         SubtypeLocale.init(context);
 
         final InputMethodManager imm = (InputMethodManager) context.getSystemService(
                 Context.INPUT_METHOD_SERVICE);
         for (final InputMethodInfo imi : imm.getInputMethodList()) {
-            if (imi.getPackageName().equals(PACKAGE)) {
+            if (imi.getPackageName().equals(packageName)) {
+                mKeyboardSubtypes = new ArrayList<InputMethodSubtype>();
                 final int subtypeCount = imi.getSubtypeCount();
                 for (int i = 0; i < subtypeCount; ++i) {
                     InputMethodSubtype subtype = imi.getSubtypeAt(i);
@@ -58,37 +53,29 @@
                 break;
             }
         }
-        assertNotNull("Can not find input method " + PACKAGE, mKeyboardSubtypes);
+        assertNotNull("Can not find input method " + packageName, mKeyboardSubtypes);
         assertTrue("Can not find keyboard subtype", mKeyboardSubtypes.size() > 0);
     }
 
-    private String getStringWithLocale(int resId, Locale locale) {
-        final Locale savedLocale = Locale.getDefault();
-        try {
-            Locale.setDefault(locale);
-            return mRes.getString(resId);
-        } finally {
-            Locale.setDefault(savedLocale);
-        }
-    }
-
     public void testSubtypeLocale() {
         final StringBuilder messages = new StringBuilder();
         int failedCount = 0;
         for (final InputMethodSubtype subtype : mKeyboardSubtypes) {
-            final String localeCode = subtype.getLocale();
-            final Locale locale = LocaleUtils.constructLocaleFromString(localeCode);
-            // The locale name which will be displayed on spacebar.  For example 'English (US)' or
-            // 'Francais (Canada)'.  (c=\u008d)
-            final String displayName = SubtypeLocale.getFullDisplayName(locale);
-            // The subtype name in its locale.  For example 'English (US) Keyboard' or
-            // 'Clavier Francais (Canada)'.  (c=\u008d)
-            final String subtypeName = getStringWithLocale(subtype.getNameResId(), locale);
-            if (subtypeName.contains(displayName)) {
+            final Locale locale = LocaleUtils.constructLocaleFromString(subtype.getLocale());
+            final String subtypeLocaleString =
+                    subtype.containsExtraValueKey(LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE)
+                    ? subtype.getExtraValueOf(LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE)
+                    : subtype.getLocale();
+            final Locale subtypeLocale = LocaleUtils.constructLocaleFromString(subtypeLocaleString);
+            // The subtype name in its locale.  For example 'English (US)' or 'Deutsch (QWERTY)'.
+            final String subtypeName = SubtypeLocale.getFullDisplayName(subtypeLocale);
+            // The locale language name in its locale.
+            final String languageName = locale.getDisplayLanguage(locale);
+            if (!subtypeName.contains(languageName)) {
                 failedCount++;
                 messages.append(String.format(
-                        "subtype name is '%s' and should contain locale '%s' name '%s'\n",
-                        subtypeName, localeCode, displayName));
+                        "subtype name is '%s' and should contain locale '%s' language name '%s'\n",
+                        subtypeName, subtypeLocale, languageName));
             }
         }
         assertEquals(messages.toString(), 0, failedCount);
diff --git a/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java b/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java
index 2bc0aab..b7ba9c7 100644
--- a/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java
+++ b/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java
@@ -23,7 +23,7 @@
 import java.util.Locale;
 
 public class UserBigramSuggestTests extends SuggestTestsBase {
-    private static final int SUGGESTION_STARTS = 6;
+    private static final int SUGGESTION_STARTS = 1;
     private static final int MAX_DATA = 20;
     private static final int DELETE_DATA = 10;
 
diff --git a/tests/src/com/android/inputmethod/latin/UtilsTests.java b/tests/src/com/android/inputmethod/latin/UtilsTests.java
index 5c0b03a..2ef4e2f 100644
--- a/tests/src/com/android/inputmethod/latin/UtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/UtilsTests.java
@@ -18,8 +18,6 @@
 
 import android.test.AndroidTestCase;
 
-import com.android.inputmethod.latin.tests.R;
-
 public class UtilsTests extends AndroidTestCase {
 
     // The following is meant to be a reasonable default for