From 5a2d0630474d6df639e97ff48f5f48b220ca4ee9 Mon Sep 17 00:00:00 2001
From: "Tadashi G. Takaoka" <takaoka@google.com>
Date: Mon, 20 Jun 2011 11:58:56 +0900
Subject: [PATCH] Remove unnecessary onRefreshKeyboard call.

When using the sliding spacebar language switch on ICS, both
LatinIME.toggleLanguage() and
InputMethodService.onCurrentInputMethodSubtypeChanged() invoke
LatinIME.onRefreshKeyboard().  This change eliminates the first one if
it isn't necessary.

This change also cleans up the followings.
  * reuse theme Context when the keyboard theme hasn't been changed.
  * clear the Keyboard cache when theme has been switched.
  * eliminates unnecessary Context reference from LatinKeyboard and
    SlidingLocaleDrawable.
  * recycle Bitmap and reuse Canvas in KeyboardView.

Bug: 4725930
Change-Id: I87366e9304879d94d12b7345adea768d86d43519
---
 .../InputMethodServiceCompatWrapper.java      |  6 +--
 .../keyboard/KeyboardSwitcher.java            | 53 +++++++++++--------
 .../inputmethod/keyboard/KeyboardView.java    |  8 ++-
 .../inputmethod/keyboard/LatinKeyboard.java   | 37 ++++++-------
 .../keyboard/SlidingLocaleDrawable.java       | 11 +---
 .../android/inputmethod/latin/LatinIME.java   |  3 +-
 6 files changed, 64 insertions(+), 54 deletions(-)

diff --git a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java
index 828aea41f6..7d8c745c32 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java
@@ -16,12 +16,12 @@
 
 package com.android.inputmethod.compat;
 
-import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-
 import android.inputmethodservice.InputMethodService;
 import android.view.inputmethod.InputMethodSubtype;
 
+import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
+import com.android.inputmethod.latin.SubtypeSwitcher;
+
 public class InputMethodServiceCompatWrapper extends InputMethodService {
     // CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED needs to be false if the API level is 10
     // or previous. Note that InputMethodSubtype was added in the API level 11.
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index af22208113..8657768ee4 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -43,7 +43,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
     private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG;
     public static final boolean DEBUG_STATE = false;
 
-    private static String sConfigDefaultKeyboardThemeId;
     public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902";
     private static final int[] KEYBOARD_THEMES = {
         R.style.KeyboardTheme,
@@ -102,7 +101,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
     // Default is SETTINGS_KEY_MODE_AUTO.
     private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO;
 
-    private int mThemeIndex;
+    private int mThemeIndex = -1;
+    private Context mThemeContext;
     private int mKeyboardWidth;
 
     private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
@@ -119,17 +119,30 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
         sInstance.mInputMethodService = ims;
         sInstance.mPrefs = prefs;
         sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance();
+        sInstance.setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs));
+        prefs.registerOnSharedPreferenceChangeListener(sInstance);
+    }
 
+    private static int getKeyboardThemeIndex(Context context, SharedPreferences prefs) {
+        final String defaultThemeId = context.getString(R.string.config_default_keyboard_theme_id);
+        final String themeId = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultThemeId);
         try {
-            sConfigDefaultKeyboardThemeId = ims.getString(
-                    R.string.config_default_keyboard_theme_id);
-            sInstance.mThemeIndex = Integer.valueOf(
-                    prefs.getString(PREF_KEYBOARD_LAYOUT, sConfigDefaultKeyboardThemeId));
+            final int themeIndex = Integer.valueOf(themeId);
+            if (themeIndex >= 0 && themeIndex < KEYBOARD_THEMES.length)
+                return themeIndex;
         } catch (NumberFormatException e) {
-            sConfigDefaultKeyboardThemeId = "0";
-            sInstance.mThemeIndex = 0;
+            // Format error, keyboard theme is default to 0.
+        }
+        Log.w(TAG, "Illegal keyboard theme in preference: " + themeId + ", default to 0");
+        return 0;
+    }
+
+    private void setContextThemeWrapper(Context context, int themeIndex) {
+        if (mThemeIndex != themeIndex) {
+            mThemeIndex = themeIndex;
+            mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]);
+            mKeyboardCache.clear();
         }
-        prefs.registerOnSharedPreferenceChangeListener(sInstance);
     }
 
     public void loadKeyboard(EditorInfo attribute, boolean voiceKeyEnabled,
@@ -202,9 +215,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
             final Locale savedLocale = Utils.setSystemLocale(res,
                     mSubtypeSwitcher.getInputLocale());
 
-            final Context themeContext = new ContextThemeWrapper(mInputMethodService,
-                    KEYBOARD_THEMES[mThemeIndex]);
-            keyboard = new LatinKeyboard(themeContext, id, id.mWidth);
+            keyboard = new LatinKeyboard(mThemeContext, id, id.mWidth);
 
             if (id.mEnableShiftLock) {
                 keyboard.enableShiftLock();
@@ -724,30 +735,29 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
         if (mKeyboardView != null) {
             mKeyboardView.closing();
         }
-        final int themeIndex = (newThemeIndex < KEYBOARD_THEMES.length) ? newThemeIndex
-                : Integer.valueOf(sConfigDefaultKeyboardThemeId);
 
+        final int oldThemeIndex = mThemeIndex;
         Utils.GCUtils.getInstance().reset();
         boolean tryGC = true;
         for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
             try {
-                final Context themeContext = new ContextThemeWrapper(mInputMethodService,
-                        KEYBOARD_THEMES[themeIndex]);
-                mCurrentInputView = LayoutInflater.from(themeContext).inflate(
+                setContextThemeWrapper(mInputMethodService, newThemeIndex);
+                mCurrentInputView = LayoutInflater.from(mThemeContext).inflate(
                         R.layout.input_view, null);
                 tryGC = false;
             } catch (OutOfMemoryError e) {
                 Log.w(TAG, "load keyboard failed: " + e);
-                tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mThemeIndex + "," + themeIndex, e);
+                tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
+                        oldThemeIndex + "," + newThemeIndex, e);
             } catch (InflateException e) {
                 Log.w(TAG, "load keyboard failed: " + e);
-                tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mThemeIndex + "," + themeIndex, e);
+                tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
+                        oldThemeIndex + "," + newThemeIndex, e);
             }
         }
 
         mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
         mKeyboardView.setOnKeyboardActionListener(mInputMethodService);
-        mThemeIndex = themeIndex;
         return mCurrentInputView;
     }
 
@@ -766,8 +776,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
     @Override
     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
         if (PREF_KEYBOARD_LAYOUT.equals(key)) {
-            final int layoutId = Integer.valueOf(
-                    sharedPreferences.getString(key, sConfigDefaultKeyboardThemeId));
+            final int layoutId = getKeyboardThemeIndex(mInputMethodService, sharedPreferences);
             postSetInputView(createInputView(layoutId, false));
         } else if (Settings.PREF_SETTINGS_KEY.equals(key)) {
             mSettingsKeyEnabledInSettings = getSettingsKeyMode(sharedPreferences,
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 44f2ff3ff9..f73cdc083a 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -626,8 +626,14 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
             mDirtyRect.union(0, 0, width, height);
         }
         if (mBuffer == null || mBuffer.getWidth() != width || mBuffer.getHeight() != height) {
+            if (mBuffer != null)
+                mBuffer.recycle();
             mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-            mCanvas = new Canvas(mBuffer);
+            if (mCanvas != null) {
+                mCanvas.setBitmap(mBuffer);
+            } else {
+                mCanvas = new Canvas(mBuffer);
+            }
         }
         final Canvas canvas = mCanvas;
         canvas.clipRect(mDirtyRect, Op.REPLACE);
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
index a6ac767513..473006deb9 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
@@ -16,9 +16,6 @@
 
 package com.android.inputmethod.keyboard;
 
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -36,6 +33,9 @@ import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.SubtypeSwitcher;
+
 import java.lang.ref.SoftReference;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -49,7 +49,8 @@ public class LatinKeyboard extends Keyboard {
     public static final int CODE_NEXT_LANGUAGE = -100;
     public static final int CODE_PREV_LANGUAGE = -101;
 
-    private final Context mContext;
+    private final Resources mRes;
+    private final Theme mTheme;
     private final SubtypeSwitcher mSubtypeSwitcher = SubtypeSwitcher.getInstance();
 
     /* Space key and its icons, drawables and colors. */
@@ -65,7 +66,7 @@ public class LatinKeyboard extends Keyboard {
     private float mSpacebarTextFadeFactor = 0.0f;
     private final int mSpacebarLanguageSwitchThreshold;
     private int mSpacebarSlidingLanguageSwitchDiff;
-    private SlidingLocaleDrawable mSlidingLocaleIcon;
+    private final SlidingLocaleDrawable mSlidingLocaleIcon;
     private final HashMap<Integer, SoftReference<BitmapDrawable>> mSpaceDrawableCache =
             new HashMap<Integer, SoftReference<BitmapDrawable>>();
 
@@ -90,7 +91,8 @@ public class LatinKeyboard extends Keyboard {
 
     public LatinKeyboard(Context context, KeyboardId id, int width) {
         super(context, id.getXmlId(), id, width);
-        mContext = context;
+        mRes = context.getResources();
+        mTheme = context.getTheme();
 
         final List<Key> keys = getKeys();
         int spaceKeyIndex = -1;
@@ -133,6 +135,13 @@ public class LatinKeyboard extends Keyboard {
 
         // The threshold is "key width" x 1.25
         mSpacebarLanguageSwitchThreshold = (getMostCommonKeyWidth() * 5) / 4;
+
+        final int spaceKeyWidth = Math.max(mSpaceKey.mWidth,
+                (int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO));
+        final int spaceKeyheight = mSpacePreviewIcon.getIntrinsicHeight();
+        mSlidingLocaleIcon = new SlidingLocaleDrawable(
+                context, mSpacePreviewIcon, spaceKeyWidth, spaceKeyheight);
+        mSlidingLocaleIcon.setBounds(0, 0, spaceKeyWidth, spaceKeyheight);
     }
 
     public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboardView view) {
@@ -250,7 +259,7 @@ public class LatinKeyboard extends Keyboard {
         final SoftReference<BitmapDrawable> ref = mSpaceDrawableCache.get(hashCode);
         BitmapDrawable drawable = (ref == null) ? null : ref.get();
         if (drawable == null) {
-            drawable = new BitmapDrawable(mContext.getResources(), drawSpacebar(
+            drawable = new BitmapDrawable(mRes, drawSpacebar(
                     locale, isAutoCorrection, mSpacebarTextFadeFactor));
             mSpaceDrawableCache.put(hashCode, new SoftReference<BitmapDrawable>(drawable));
         }
@@ -263,7 +272,7 @@ public class LatinKeyboard extends Keyboard {
         final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight;
         final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
         final Canvas canvas = new Canvas(buffer);
-        final Resources res = mContext.getResources();
+        final Resources res = mRes;
         canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
 
         // If application locales are explicitly selected.
@@ -287,7 +296,7 @@ public class LatinKeyboard extends Keyboard {
 
             final String language = layoutSpacebar(paint, inputLocale,
                     mSpacebarArrowLeftIcon, mSpacebarArrowRightIcon, width, height,
-                    getTextSizeFromTheme(mContext.getTheme(), textStyle, defaultTextSize));
+                    getTextSizeFromTheme(mTheme, textStyle, defaultTextSize));
 
             // Draw language text with shadow
             // In case there is no space icon, we will place the language text at the center of
@@ -341,14 +350,6 @@ public class LatinKeyboard extends Keyboard {
         if (mSpacebarSlidingLanguageSwitchDiff == diff)
             return;
         mSpacebarSlidingLanguageSwitchDiff = diff;
-        if (mSlidingLocaleIcon == null) {
-            final int width = Math.max(mSpaceKey.mWidth,
-                    (int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO));
-            final int height = mSpacePreviewIcon.getIntrinsicHeight();
-            mSlidingLocaleIcon =
-                    new SlidingLocaleDrawable(mContext, mSpacePreviewIcon, width, height);
-            mSlidingLocaleIcon.setBounds(0, 0, width, height);
-        }
         mSlidingLocaleIcon.setDiff(diff);
         if (Math.abs(diff) == Integer.MAX_VALUE) {
             mSpaceKey.setPreviewIcon(mSpacePreviewIcon);
@@ -403,7 +404,7 @@ public class LatinKeyboard extends Keyboard {
                 Math.max(0, Math.min(y, getHeight() - 1)));
     }
 
-    private static int getTextSizeFromTheme(Theme theme, int style, int defValue) {
+    public static int getTextSizeFromTheme(Theme theme, int style, int defValue) {
         TypedArray array = theme.obtainStyledAttributes(
                 style, new int[] { android.R.attr.textSize });
         int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
diff --git a/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java b/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java
index a20bf1cd3e..dd271de645 100644
--- a/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java
+++ b/java/src/com/android/inputmethod/keyboard/SlidingLocaleDrawable.java
@@ -60,8 +60,8 @@ public class SlidingLocaleDrawable extends Drawable {
         mWidth = width;
         mHeight = height;
         final TextPaint textPaint = new TextPaint();
-        textPaint.setTextSize(getTextSizeFromTheme(
-                context, android.R.style.TextAppearance_Medium, 18));
+        textPaint.setTextSize(LatinKeyboard.getTextSizeFromTheme(
+                context.getTheme(), android.R.style.TextAppearance_Medium, 18));
         textPaint.setColor(Color.TRANSPARENT);
         textPaint.setTextAlign(Align.CENTER);
         textPaint.setAntiAlias(true);
@@ -78,13 +78,6 @@ public class SlidingLocaleDrawable extends Drawable {
         mThreshold = ViewConfiguration.get(context).getScaledTouchSlop();
     }
 
-    private static int getTextSizeFromTheme(Context context, int style, int defValue) {
-        TypedArray array = context.getTheme().obtainStyledAttributes(
-                style, new int[] { android.R.attr.textSize });
-        int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
-        return textSize;
-    }
-
     void setDiff(int diff) {
         if (diff == Integer.MAX_VALUE) {
             mHitThreshold = false;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 7446aff9ee..fd4a47c39a 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1871,7 +1871,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
         }
         // The following is necessary because on API levels < 10, we don't get notified when
         // subtype changes.
-        onRefreshKeyboard();
+        if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED)
+            onRefreshKeyboard();
      }
 
     @Override
-- 
GitLab