From 673c727b7a42e2cee2df4415111bfa94a0a2df3b Mon Sep 17 00:00:00 2001
From: Jean Chalard <jchalard@google.com>
Date: Thu, 13 Jun 2013 15:26:47 +0900
Subject: [PATCH] Defer disk-intensive tasks until after the keyboard is shown

Bug: 8689779
Change-Id: Ia78d3540f44ec0028c3246a8e0163e9ecf061ecf
---
 .../android/inputmethod/latin/LatinIME.java   | 42 +++++++++++++++----
 1 file changed, 33 insertions(+), 9 deletions(-)

diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 73ec57871f..52a9b9a6cc 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -201,6 +201,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         private static final int MSG_UPDATE_SUGGESTION_STRIP = 2;
         private static final int MSG_SHOW_GESTURE_PREVIEW_AND_SUGGESTION_STRIP = 3;
         private static final int MSG_RESUME_SUGGESTIONS = 4;
+        private static final int MSG_REOPEN_DICTIONARIES = 5;
 
         private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
 
@@ -241,6 +242,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
             case MSG_RESUME_SUGGESTIONS:
                 latinIme.restartSuggestionsOnWordTouchedByCursor();
                 break;
+            case MSG_REOPEN_DICTIONARIES:
+                latinIme.initSuggest();
+                // In theory we could call latinIme.updateSuggestionStrip() right away, but
+                // in the practice, the dictionary is not finished opening yet so we wouldn't
+                // get any suggestions. Wait one frame.
+                postUpdateSuggestionStrip();
+                break;
             }
         }
 
@@ -248,6 +256,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
             sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION_STRIP), mDelayUpdateSuggestions);
         }
 
+        public void postReopenDictionaries() {
+            sendMessage(obtainMessage(MSG_REOPEN_DICTIONARIES));
+        }
+
         public void postResumeSuggestions() {
             removeMessages(MSG_RESUME_SUGGESTIONS);
             sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS), mDelayUpdateSuggestions);
@@ -261,6 +273,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
             return hasMessages(MSG_UPDATE_SUGGESTION_STRIP);
         }
 
+        public boolean hasPendingReopenDictionaries() {
+            return hasMessages(MSG_REOPEN_DICTIONARIES);
+        }
+
         public void postUpdateShiftState() {
             removeMessages(MSG_UPDATE_SHIFT_STATE);
             sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), mDelayUpdateShiftState);
@@ -474,8 +490,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
                 new InputAttributes(getCurrentInputEditorInfo(), isFullscreenMode());
         mSettings.loadSettings(locale, inputAttributes);
         AudioAndHapticFeedbackManager.getInstance().onSettingsChanged(mSettings.getCurrent());
-        // May need to reset the contacts dictionary depending on the user settings.
-        resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
+        // To load the keyboard we need to load all the settings once, but resetting the
+        // contacts dictionary should be deferred until after the new layout has been displayed
+        // to improve responsivity. In the language switching process, we post a reopenDictionaries
+        // message, then come here to read the settings for the new language before we change
+        // the layout; at this time, we need to skip resetting the contacts dictionary. It will
+        // be done later inside {@see #initSuggest()} when the reopenDictionaries message is
+        // processed.
+        if (!mHandler.hasPendingReopenDictionaries()) {
+            // May need to reset the contacts dictionary depending on the user settings.
+            resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
+        }
     }
 
     // Note that this method is called from a non-UI thread.
@@ -2619,18 +2644,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
     // Outside LatinIME, only used by the {@link InputTestsBase} test suite.
     @UsedForTesting
     void loadKeyboard() {
-        // TODO: Why are we calling {@link #loadSettings()} and {@link #initSuggest()} in a
-        // different order than in {@link #onStartInputView}?
-        initSuggest();
+        // Since we are switching languages, the most urgent thing is to let the keyboard graphics
+        // update. LoadKeyboard does that, but we need to wait for buffer flip for it to be on
+        // the screen. Anything we do right now will delay this, so wait until the next frame
+        // before we do the rest, like reopening dictionaries and updating suggestions. So we
+        // post a message.
+        mHandler.postReopenDictionaries();
         loadSettings();
         if (mKeyboardSwitcher.getMainKeyboardView() != null) {
             // Reload keyboard because the current language has been changed.
             mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettings.getCurrent());
         }
-        // Since we just changed languages, we should re-evaluate suggestions with whatever word
-        // we are currently composing. If we are not composing anything, we may want to display
-        // predictions or punctuation signs (which is done by the updateSuggestionStrip anyway).
-        mHandler.postUpdateSuggestionStrip();
     }
 
     // Callback called by PointerTracker through the KeyboardActionListener. This is called when a
-- 
GitLab