Reconcile with jb-mr1-release - do not merge

Change-Id: I19e7e1476178dc94e3debb6bec3241b3d9070db0
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index a0f48d2..1183b5f 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -120,7 +120,6 @@
             spannable = new SpannableString(pickedWord);
         }
         final ArrayList<String> suggestionsList = new ArrayList<String>();
-        boolean sameAsTyped = false;
         for (int i = 0; i < suggestedWords.size(); ++i) {
             if (suggestionsList.size() >= OBJ_SUGGESTIONS_MAX_SIZE) {
                 break;
@@ -128,8 +127,6 @@
             final CharSequence word = suggestedWords.getWord(i);
             if (!TextUtils.equals(pickedWord, word)) {
                 suggestionsList.add(word.toString());
-            } else if (i == 0) {
-                sameAsTyped = true;
             }
         }
 
diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
index a3b7776..97d88af 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
@@ -37,8 +37,9 @@
     }
 
     public void setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
-        if (keyboard == null)
+        if (keyboard == null) {
             throw new NullPointerException();
+        }
         mCorrectionX = (int)correctionX;
         mCorrectionY = (int)correctionY;
         mKeyboard = keyboard;
@@ -58,8 +59,6 @@
     }
 
     public Keyboard getKeyboard() {
-        if (mKeyboard == null)
-            throw new IllegalStateException("keyboard isn't set");
         return mKeyboard;
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
index cd4e300..a183546 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
@@ -39,7 +39,11 @@
 
         Key nearestKey = null;
         int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
-        for (final Key key : getKeyboard().mKeys) {
+        final Keyboard keyboard = getKeyboard();
+        if (keyboard == null) {
+            throw new NullPointerException("Keyboard isn't set");
+        }
+        for (final Key key : keyboard.mKeys) {
             final int dist = key.squaredDistanceToEdge(touchX, touchY);
             if (dist < nearestDist) {
                 nearestKey = key;
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index fd40aa6..60fe17b 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -16,8 +16,6 @@
 
 package com.android.inputmethod.latin;
 
-import android.text.TextUtils;
-
 import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 88ac07d..ee80f25 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -65,7 +65,7 @@
                 prevWord, proximityInfo);
         if (null == suggestions) suggestions = new ArrayList<SuggestedWordInfo>();
         final int length = dictionaries.size();
-        for (int i = 0; i < length; ++ i) {
+        for (int i = 1; i < length; ++ i) {
             final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getSuggestions(composer,
                     prevWord, proximityInfo);
             if (null != sugg) suggestions.addAll(sugg);
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index f8a6fc8..1e700f5 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -545,8 +545,9 @@
             commitTyped(LastComposedWord.NOT_A_SEPARATOR);
             mConnection.finishComposingText();
             mConnection.endBatchEdit();
-            if (isShowingOptionDialog())
+            if (isShowingOptionDialog()) {
                 mOptionsDialog.dismiss();
+            }
         }
         super.onConfigurationChanged(conf);
     }
@@ -1046,7 +1047,6 @@
                     LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(),
                     separatorCode, prevWord);
         }
-        updateSuggestionStrip();
     }
 
     // Called from the KeyboardSwitcher which needs to know auto caps state to display
@@ -1330,10 +1330,11 @@
 
     // Called from PointerTracker through the KeyboardActionListener interface
     @Override
-    public void onTextInput(CharSequence text) {
+    public void onTextInput(CharSequence rawText) {
         mConnection.beginBatchEdit();
         commitTyped(LastComposedWord.NOT_A_SEPARATOR);
-        text = specificTldProcessingOnTextInput(text);
+        mHandler.postUpdateSuggestionStrip();
+        final CharSequence text = specificTldProcessingOnTextInput(rawText);
         if (SPACE_STATE_PHANTOM == mSpaceState) {
             sendKeyCodePoint(Keyboard.CODE_SPACE);
         }
@@ -1688,8 +1689,9 @@
         commitTyped(LastComposedWord.NOT_A_SEPARATOR);
         requestHideSelf(0);
         MainKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
-        if (inputView != null)
+        if (inputView != null) {
             inputView.closing();
+        }
     }
 
     // TODO: make this private
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 8f71de0..c6b5c33 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -44,7 +44,6 @@
 import java.io.PrintWriter;
 import java.nio.channels.FileChannel;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
 
@@ -220,7 +219,7 @@
     }
 
     public static String getStackTrace() {
-        return getStackTrace(Integer.MAX_VALUE);
+        return getStackTrace(Integer.MAX_VALUE - 1);
     }
 
     public static class UsabilityStudyLogUtils {
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 2b30f3c..31dd61e 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -25,17 +25,52 @@
 #define AKLOGE(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##__VA_ARGS__)
 #define AKLOGI(fmt, ...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, fmt, ##__VA_ARGS__)
 
+#define DUMP_RESULT(words, frequencies, maxWordCount, maxWordLength) do { \
+        dumpResult(words, frequencies, maxWordCount, maxWordLength); } while(0)
 #define DUMP_WORD(word, length) do { dumpWord(word, length); } while(0)
 #define DUMP_WORD_INT(word, length) do { dumpWordInt(word, length); } while(0)
 
+static inline void dumpWordInfo(const unsigned short *word, const int length,
+        const int rank, const int frequency) {
+    static char charBuf[50];
+    int i = 0;
+    for (; i < length; ++i) {
+        const unsigned short c = word[i];
+        if (c == 0) {
+            break;
+        }
+        charBuf[i] = c;
+    }
+    charBuf[i] = 0;
+    if (i > 1) {
+        AKLOGI("%2d [ %s ] (%d)", rank, charBuf, frequency);
+    }
+}
+
+static inline void dumpResult(
+        const unsigned short *outWords, const int *frequencies, const int maxWordCounts,
+        const int maxWordLength) {
+    AKLOGI("--- DUMP RESULT ---------");
+    for (int i = 0; i < maxWordCounts; ++i) {
+        dumpWordInfo(&outWords[i * maxWordLength], maxWordLength, i, frequencies[i]);
+    }
+    AKLOGI("-------------------------");
+}
+
 static inline void dumpWord(const unsigned short *word, const int length) {
     static char charBuf[50];
-
-    for (int i = 0; i < length; ++i) {
-        charBuf[i] = word[i];
+    int i = 0;
+    for (; i < length; ++i) {
+        const unsigned short c = word[i];
+        if (c == 0) {
+            break;
+        }
+        charBuf[i] = c;
     }
-    charBuf[length] = 0;
-    AKLOGI("[ %s ]", charBuf);
+    charBuf[i] = 0;
+    if (i > 1) {
+        AKLOGI("[ %s ]", charBuf);
+    }
 }
 
 static inline void dumpWordInt(const int *word, const int length) {
@@ -51,6 +86,7 @@
 #else
 #define AKLOGE(fmt, ...)
 #define AKLOGI(fmt, ...)
+#define DUMP_RESULT(words, frequencies, maxWordCount, maxWordLength)
 #define DUMP_WORD(word, length)
 #define DUMP_WORD_INT(word, length)
 #endif
diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp
index 6c72211..ee55cfa 100644
--- a/native/jni/src/dictionary.cpp
+++ b/native/jni/src/dictionary.cpp
@@ -67,6 +67,9 @@
         result = mGestureDecoder->getSuggestions(proximityInfo, xcoordinates, ycoordinates,
                 times, pointerIds, codes, codesSize, commitPoint,
                 outWords, frequencies, spaceIndices, outputTypes);
+        if (DEBUG_DICT) {
+            DUMP_RESULT(outWords, frequencies, 18 /* MAX_WORDS */, MAX_WORD_LENGTH_INTERNAL);
+        }
         return result;
     } else {
         std::map<int, int> bigramMap;