Merge "Make action key background more visually prominent"
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 93933f1..16dccf8 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -306,12 +306,10 @@
         Arrays.fill(mScores, 0);
 
         // Save a lowercase version of the original word
-        CharSequence typedWord = wordComposer.getTypedWord();
+        String typedWord = wordComposer.getTypedWord();
         if (typedWord != null) {
-            final String typedWordString = typedWord.toString();
-            typedWord = typedWordString;
             // Treating USER_TYPED as UNIGRAM suggestion for logging now.
-            LatinImeLogger.onAddSuggestedWord(typedWordString, Suggest.DIC_USER_TYPED,
+            LatinImeLogger.onAddSuggestedWord(typedWord, Suggest.DIC_USER_TYPED,
                     Dictionary.DataType.UNIGRAM);
         }
         mTypedWord = typedWord;
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 24519ad..a79e6dc 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -164,11 +164,11 @@
      * Returns the word as it was typed, without any correction applied.
      * @return the word that was typed so far
      */
-    public CharSequence getTypedWord() {
+    public String getTypedWord() {
         if (size() == 0) {
             return null;
         }
-        return mTypedWord;
+        return mTypedWord.toString();
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index dfa0abf..bf2e90d 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -327,67 +327,78 @@
         @Override
         public SuggestionsInfo onGetSuggestions(final TextInfo textInfo,
                 final int suggestionsLimit) {
-            final String text = textInfo.getText();
-
-            if (shouldFilterOut(text)) return EMPTY_SUGGESTIONS_INFO;
-
-            final SuggestionsGatherer suggestionsGatherer =
-                    new SuggestionsGatherer(suggestionsLimit);
-            final WordComposer composer = new WordComposer();
-            final int length = text.length();
-            for (int i = 0; i < length; ++i) {
-                final int character = text.codePointAt(i);
-                final int proximityIndex = SpellCheckerProximityInfo.getIndexOf(character);
-                final int[] proximities;
-                if (-1 == proximityIndex) {
-                    proximities = new int[] { character };
-                } else {
-                    proximities = Arrays.copyOfRange(SpellCheckerProximityInfo.PROXIMITY,
-                            proximityIndex, proximityIndex + SpellCheckerProximityInfo.ROW_SIZE);
-                }
-                composer.add(character, proximities,
-                        WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
-            }
-
-            final int capitalizeType = getCapitalizationType(text);
-            boolean isInDict = true;
             try {
-                final DictAndProximity dictInfo = mDictionaryPool.take();
-                dictInfo.mDictionary.getWords(composer, suggestionsGatherer,
-                        dictInfo.mProximityInfo);
-                isInDict = dictInfo.mDictionary.isValidWord(text);
-                if (!isInDict && CAPITALIZE_NONE != capitalizeType) {
-                    // We want to test the word again if it's all caps or first caps only.
-                    // If it's fully down, we already tested it, if it's mixed case, we don't
-                    // want to test a lowercase version of it.
-                    isInDict = dictInfo.mDictionary.isValidWord(text.toLowerCase(mLocale));
-                }
-                if (!mDictionaryPool.offer(dictInfo)) {
-                    Log.e(TAG, "Can't re-insert a dictionary into its pool");
-                }
-            } catch (InterruptedException e) {
-                // I don't think this can happen.
-                return EMPTY_SUGGESTIONS_INFO;
-            }
+                final String text = textInfo.getText();
 
-            final SuggestionsGatherer.Result result = suggestionsGatherer.getResults(text,
-                    mService.mTypoThreshold, capitalizeType, mLocale);
+                if (shouldFilterOut(text)) return EMPTY_SUGGESTIONS_INFO;
 
-            if (DBG) {
-                Log.i(TAG, "Spell checking results for " + text + " with suggestion limit "
-                        + suggestionsLimit);
-                Log.i(TAG, "IsInDict = " + result.mLooksLikeTypo);
-                Log.i(TAG, "LooksLikeTypo = " + result.mLooksLikeTypo);
-                for (String suggestion : result.mSuggestions) {
-                    Log.i(TAG, suggestion);
+                final SuggestionsGatherer suggestionsGatherer =
+                        new SuggestionsGatherer(suggestionsLimit);
+                final WordComposer composer = new WordComposer();
+                final int length = text.length();
+                for (int i = 0; i < length; ++i) {
+                    final int character = text.codePointAt(i);
+                    final int proximityIndex = SpellCheckerProximityInfo.getIndexOf(character);
+                    final int[] proximities;
+                    if (-1 == proximityIndex) {
+                        proximities = new int[] { character };
+                    } else {
+                        proximities = Arrays.copyOfRange(SpellCheckerProximityInfo.PROXIMITY,
+                                proximityIndex,
+                                proximityIndex + SpellCheckerProximityInfo.ROW_SIZE);
+                    }
+                    composer.add(character, proximities,
+                            WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
+                }
+
+                final int capitalizeType = getCapitalizationType(text);
+                boolean isInDict = true;
+                try {
+                    final DictAndProximity dictInfo = mDictionaryPool.take();
+                    dictInfo.mDictionary.getWords(composer, suggestionsGatherer,
+                            dictInfo.mProximityInfo);
+                    isInDict = dictInfo.mDictionary.isValidWord(text);
+                    if (!isInDict && CAPITALIZE_NONE != capitalizeType) {
+                        // We want to test the word again if it's all caps or first caps only.
+                        // If it's fully down, we already tested it, if it's mixed case, we don't
+                        // want to test a lowercase version of it.
+                        isInDict = dictInfo.mDictionary.isValidWord(text.toLowerCase(mLocale));
+                    }
+                    if (!mDictionaryPool.offer(dictInfo)) {
+                        Log.e(TAG, "Can't re-insert a dictionary into its pool");
+                    }
+                } catch (InterruptedException e) {
+                    // I don't think this can happen.
+                    return EMPTY_SUGGESTIONS_INFO;
+                }
+
+                final SuggestionsGatherer.Result result = suggestionsGatherer.getResults(text,
+                        mService.mTypoThreshold, capitalizeType, mLocale);
+
+                if (DBG) {
+                    Log.i(TAG, "Spell checking results for " + text + " with suggestion limit "
+                            + suggestionsLimit);
+                    Log.i(TAG, "IsInDict = " + result.mLooksLikeTypo);
+                    Log.i(TAG, "LooksLikeTypo = " + result.mLooksLikeTypo);
+                    for (String suggestion : result.mSuggestions) {
+                        Log.i(TAG, suggestion);
+                    }
+                }
+
+                final int flags =
+                        (isInDict ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY : 0)
+                                | (result.mLooksLikeTypo
+                                        ? SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO : 0);
+                return new SuggestionsInfo(flags, result.mSuggestions);
+            } catch (RuntimeException e) {
+                // Don't kill the keyboard if there is a bug in the spell checker
+                if (DBG) {
+                    throw e;
+                } else {
+                    Log.e(TAG, "Exception while spellcheking: " + e);
+                    return EMPTY_SUGGESTIONS_INFO;
                 }
             }
-
-            final int flags =
-                    (isInDict ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY : 0)
-                            | (result.mLooksLikeTypo
-                                    ? SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO : 0);
-            return new SuggestionsInfo(flags, result.mSuggestions);
         }
     }
 }