From ff6445ed0eac57f9daf573178ffe9f4e1e2b246a Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 11 Jun 2013 17:33:58 +0900 Subject: [PATCH] Cache subtype lists reasonably. This will spare a lot of IPC for Latin IME at the cost of very little retained memory. This improves the loading by potentially a lot - between 15 and 30% when the layout is cached (which should now be the case almost every time), and half that if it's not. More importantly, it makes the load time less sensitive to high device load, which is one of the sore points. Bug: 8689779 Change-Id: I2e07736f1a92c38eed0e203bc690761a181da8b9 --- .../android/inputmethod/latin/LatinIME.java | 2 + .../latin/RichInputMethodManager.java | 42 +++++++++++++++---- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 0bf167fd4..da1eb6557 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -855,8 +855,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } // Remove pending messages related to update suggestions mHandler.cancelUpdateSuggestionStrip(); + // Should do the following in onFinishInputInternal but until JB MR2 it's not called :( if (mWordComposer.isComposingWord()) mConnection.finishComposingText(); resetComposingState(true /* alsoResetLastComposedWord */); + mRichImm.clearSubtypeCaches(); // Notify ResearchLogger if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_onFinishInputViewInternal(finishingInput, mLastSelectionStart, diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java index 94513e635..86f75635d 100644 --- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java +++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java @@ -30,6 +30,7 @@ import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; import java.util.Collections; +import java.util.HashMap; import java.util.List; /** @@ -46,6 +47,10 @@ public final class RichInputMethodManager { private InputMethodManagerCompatWrapper mImmWrapper; private InputMethodInfo mInputMethodInfoOfThisIme; + final HashMap> + mSubtypeListCacheWithImplicitlySelectedSubtypes = CollectionUtils.newHashMap(); + final HashMap> + mSubtypeListCacheWithoutImplicitlySelectedSubtypes = CollectionUtils.newHashMap(); private static final int INDEX_NOT_FOUND = -1; @@ -102,8 +107,8 @@ public final class RichInputMethodManager { public List getMyEnabledInputMethodSubtypeList( boolean allowsImplicitlySelectedSubtypes) { - return mImmWrapper.mImm.getEnabledInputMethodSubtypeList( - mInputMethodInfoOfThisIme, allowsImplicitlySelectedSubtypes); + return getEnabledInputMethodSubtypeList(mInputMethodInfoOfThisIme, + allowsImplicitlySelectedSubtypes); } public boolean switchToNextInputMethod(final IBinder token, final boolean onlyCurrentIme) { @@ -151,8 +156,8 @@ public final class RichInputMethodManager { return false; } final InputMethodInfo nextImi = getNextNonAuxiliaryIme(currentIndex, enabledImis); - final List enabledSubtypes = imm.getEnabledInputMethodSubtypeList( - nextImi, true /* allowsImplicitlySelectedSubtypes */); + final List enabledSubtypes = getEnabledInputMethodSubtypeList(nextImi, + true /* allowsImplicitlySelectedSubtypes */); if (enabledSubtypes.isEmpty()) { // The next IME has no subtype. imm.setInputMethod(token, nextImi.getId()); @@ -227,9 +232,8 @@ public final class RichInputMethodManager { public boolean checkIfSubtypeBelongsToImeAndEnabled(final InputMethodInfo imi, final InputMethodSubtype subtype) { - return checkIfSubtypeBelongsToList( - subtype, mImmWrapper.mImm.getEnabledInputMethodSubtypeList( - imi, true /* allowsImplicitlySelectedSubtypes */)); + return checkIfSubtypeBelongsToList(subtype, getEnabledInputMethodSubtypeList(imi, + true /* allowsImplicitlySelectedSubtypes */)); } private static boolean checkIfSubtypeBelongsToList(final InputMethodSubtype subtype, @@ -290,8 +294,7 @@ public final class RichInputMethodManager { for (InputMethodInfo imi : imiList) { // We can return true immediately after we find two or more filtered IMEs. if (filteredImisCount > 1) return true; - final List subtypes = - mImmWrapper.mImm.getEnabledInputMethodSubtypeList(imi, true); + final List subtypes = getEnabledInputMethodSubtypeList(imi, true); // IMEs that have no subtypes should be counted. if (subtypes.isEmpty()) { ++filteredImisCount; @@ -354,5 +357,26 @@ public final class RichInputMethodManager { public void setAdditionalInputMethodSubtypes(final InputMethodSubtype[] subtypes) { mImmWrapper.mImm.setAdditionalInputMethodSubtypes( mInputMethodInfoOfThisIme.getId(), subtypes); + // Clear the cache so that we go read the subtypes again next time. + clearSubtypeCaches(); + } + + private List getEnabledInputMethodSubtypeList(final InputMethodInfo imi, + final boolean allowsImplicitlySelectedSubtypes) { + final HashMap> cache = + allowsImplicitlySelectedSubtypes + ? mSubtypeListCacheWithImplicitlySelectedSubtypes + : mSubtypeListCacheWithoutImplicitlySelectedSubtypes; + final List cachedList = cache.get(imi); + if (null != cachedList) return cachedList; + final List result = mImmWrapper.mImm.getEnabledInputMethodSubtypeList( + imi, allowsImplicitlySelectedSubtypes); + cache.put(imi, result); + return result; + } + + public void clearSubtypeCaches() { + mSubtypeListCacheWithImplicitlySelectedSubtypes.clear(); + mSubtypeListCacheWithoutImplicitlySelectedSubtypes.clear(); } }