Merge "[HW5] Make the word composer package private."
diff --git a/dictionaries/es_wordlist.combined.gz b/dictionaries/es_wordlist.combined.gz
index 41a914c..8bb2102 100644
--- a/dictionaries/es_wordlist.combined.gz
+++ b/dictionaries/es_wordlist.combined.gz
Binary files differ
diff --git a/java/res/raw/main_es.dict b/java/res/raw/main_es.dict
index 3c99e73..8c42fda 100644
--- a/java/res/raw/main_es.dict
+++ b/java/res/raw/main_es.dict
Binary files differ
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 1c5183d..d2c4ca7 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -112,6 +112,8 @@
 
     private static final int PENDING_IMS_CALLBACK_DURATION = 800;
 
+    private static final int DELAY_WAIT_FOR_DICTIONARY_LOAD = 2000; // 2s
+
     private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2;
 
     /**
@@ -171,8 +173,9 @@
         private static final int MSG_REOPEN_DICTIONARIES = 5;
         private static final int MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED = 6;
         private static final int MSG_RESET_CACHES = 7;
+        private static final int MSG_WAIT_FOR_DICTIONARY_LOAD = 8;
         // Update this when adding new messages
-        private static final int MSG_LAST = MSG_RESET_CACHES;
+        private static final int MSG_LAST = MSG_WAIT_FOR_DICTIONARY_LOAD;
 
         private static final int ARG1_NOT_GESTURE_INPUT = 0;
         private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
@@ -234,7 +237,7 @@
                 latinIme.resetSuggest();
                 // We need to re-evaluate the currently composing word in case the script has
                 // changed.
-                postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */);
+                postWaitForDictionaryLoad();
                 break;
             case MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED:
                 latinIme.mInputLogic.onUpdateTailBatchInputCompleted(
@@ -253,6 +256,9 @@
                             latinIme.getCurrentRecapitalizeState());
                 }
                 break;
+            case MSG_WAIT_FOR_DICTIONARY_LOAD:
+                Log.i(TAG, "Timeout waiting for dictionary load");
+                break;
             }
         }
 
@@ -264,7 +270,8 @@
             sendMessage(obtainMessage(MSG_REOPEN_DICTIONARIES));
         }
 
-        public void postResumeSuggestions(final boolean shouldIncludeResumedWordInSuggestions) {
+        public void postResumeSuggestions(final boolean shouldIncludeResumedWordInSuggestions,
+                final boolean shouldDelay) {
             final LatinIME latinIme = getOwnerInstance();
             if (latinIme == null) {
                 return;
@@ -274,10 +281,16 @@
                 return;
             }
             removeMessages(MSG_RESUME_SUGGESTIONS);
-            sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS,
-                    shouldIncludeResumedWordInSuggestions ? ARG1_TRUE : ARG1_FALSE,
-                            0 /* ignored */),
-                    mDelayUpdateSuggestions);
+            if (shouldDelay) {
+                sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS,
+                                shouldIncludeResumedWordInSuggestions ? ARG1_TRUE : ARG1_FALSE,
+                                0 /* ignored */),
+                        mDelayUpdateSuggestions);
+            } else {
+                sendMessage(obtainMessage(MSG_RESUME_SUGGESTIONS,
+                        shouldIncludeResumedWordInSuggestions ? ARG1_TRUE : ARG1_FALSE,
+                        0 /* ignored */));
+            }
         }
 
         public void postResetCaches(final boolean tryResumeSuggestions, final int remainingTries) {
@@ -286,6 +299,19 @@
                     remainingTries, null));
         }
 
+        public void postWaitForDictionaryLoad() {
+            sendMessageDelayed(obtainMessage(MSG_WAIT_FOR_DICTIONARY_LOAD),
+                    DELAY_WAIT_FOR_DICTIONARY_LOAD);
+        }
+
+        public void cancelWaitForDictionaryLoad() {
+            removeMessages(MSG_WAIT_FOR_DICTIONARY_LOAD);
+        }
+
+        public boolean hasPendingWaitForDictionaryLoad() {
+            return hasMessages(MSG_WAIT_FOR_DICTIONARY_LOAD);
+        }
+
         public void cancelUpdateSuggestionStrip() {
             removeMessages(MSG_UPDATE_SUGGESTION_STRIP);
         }
@@ -582,6 +608,11 @@
         if (mainKeyboardView != null) {
             mainKeyboardView.setMainDictionaryAvailability(isMainDictionaryAvailable);
         }
+        if (mHandler.hasPendingWaitForDictionaryLoad()) {
+            mHandler.cancelWaitForDictionaryLoad();
+            mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
+                    false /* shouldDelay */);
+        }
     }
 
     private void resetSuggest() {
@@ -812,7 +843,8 @@
             // When rotating, initialSelStart and initialSelEnd sometimes are lying. Make a best
             // effort to work around this bug.
             mInputLogic.mConnection.tryFixLyingCursorPosition();
-            mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */);
+            mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
+                    true /* shouldDelay */);
             canReachInputConnection = true;
         }
 
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 7d3c423..5ab7db8 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -380,7 +380,8 @@
         // The cursor has been moved : we now accept to perform recapitalization
         mRecapitalizeStatus.enable();
         // We moved the cursor. If we are touching a word, we need to resume suggestion.
-        mLatinIME.mHandler.postResumeSuggestions(false /* shouldIncludeResumedWordInSuggestions */);
+        mLatinIME.mHandler.postResumeSuggestions(false /* shouldIncludeResumedWordInSuggestions */,
+                true /* shouldDelay */);
         // Stop the last recapitalization, if started.
         mRecapitalizeStatus.stop();
         return true;
@@ -1979,7 +1980,8 @@
         if (tryResumeSuggestions) {
             // This is triggered when starting input anew, so we want to include the resumed
             // word in suggestions.
-            handler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */);
+            handler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
+                    true /* shouldDelay */);
         }
         return true;
     }
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index efb076f..de9475a 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -626,13 +626,17 @@
 
     public void testSwitchLanguages() {
         final String WORD_TO_TYPE_FIRST_PART = "com";
-        final String WORD_TO_TYPE_SECOND_PART = "md ";
-        final String EXPECTED_RESULT = "comme ";
+        final String WORD_TO_TYPE_SECOND_PART = "md";
+        final String EXPECTED_RESULT = "comme";
         changeLanguage("en");
         type(WORD_TO_TYPE_FIRST_PART);
         changeLanguage("fr");
+        runMessages();
         type(WORD_TO_TYPE_SECOND_PART);
-        assertEquals("Composing continues after switching languages", EXPECTED_RESULT,
-                mEditText.getText().toString());
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        runMessages();
+        final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
+        assertEquals("Suggestions updated after switching languages",
+                    EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(1) : null);
     }
 }