From acbe38f3e12ce5af668c687296908a1787c85ad9 Mon Sep 17 00:00:00 2001 From: satok Date: Tue, 8 Jun 2010 11:45:21 +0900 Subject: [PATCH] Try GC at OutOfMemoryError Change-Id: Icfaecc6a0e8858622649ce9115ab94b00e240cc2 --- .../inputmethod/latin/KeyboardSwitcher.java | 17 +++-- .../android/inputmethod/latin/LatinIME.java | 15 +++-- .../inputmethod/latin/LatinIMEUtil.java | 63 +++++++++++++++++++ .../inputmethod/latin/LatinImeLogger.java | 2 +- .../inputmethod/latin/LatinKeyboardView.java | 13 ++-- 5 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 java/src/com/android/inputmethod/latin/LatinIMEUtil.java diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index a8be2fd44..ba78a902d 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -389,11 +389,18 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha if (LAYOUTS.length <= newLayout) { newLayout = Integer.valueOf(DEFAULT_LAYOUT_ID); } - try { - mInputView = (LatinKeyboardView) mInputMethodService.getLayoutInflater().inflate( - LAYOUTS[newLayout], null); - } catch (OutOfMemoryError e) { - LatinImeLogger.logOnException(mLayoutId + "," + newLayout, e); + + LatinIMEUtil.GCUtils.getInstance().reset(); + boolean tryGC = true; + for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { + try { + mInputView = (LatinKeyboardView) mInputMethodService.getLayoutInflater( + ).inflate(LAYOUTS[newLayout], null); + tryGC = false; + } catch (OutOfMemoryError e) { + tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait( + mLayoutId + "," + newLayout, e); + } } mInputView.setExtentionLayoutResId(LAYOUTS[newLayout]); mInputView.setOnKeyboardActionListener(mInputMethodService); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index e4f096628..18e5b4106 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -291,11 +291,18 @@ public class LatinIME extends InputMethodService if (inputLanguage == null) { inputLanguage = conf.locale.toString(); } - try { - initSuggest(inputLanguage); - } catch (OutOfMemoryError e) { - LatinImeLogger.logOnException(inputLanguage, e); + + LatinIMEUtil.GCUtils.getInstance().reset(); + boolean tryGC = true; + for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { + try { + initSuggest(inputLanguage); + tryGC = false; + } catch (OutOfMemoryError e) { + tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait(inputLanguage, e); + } } + mOrientation = conf.orientation; initSuggestPuncList(); diff --git a/java/src/com/android/inputmethod/latin/LatinIMEUtil.java b/java/src/com/android/inputmethod/latin/LatinIMEUtil.java new file mode 100644 index 000000000..c870b0185 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/LatinIMEUtil.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +import android.text.format.DateUtils; +import android.util.Log; + +public class LatinIMEUtil { + public static class GCUtils { + private static final String TAG = "GCUtils"; + public static final int GC_TRY_COUNT = 2; + // GC_TRY_LOOP_MAX is used for the hard limit of GC wait, + // GC_TRY_LOOP_MAX should be GC_TRY_COUNT. + public static final int GC_TRY_LOOP_MAX = 5; + private static final long GC_INTERVAL = DateUtils.SECOND_IN_MILLIS; + private static GCUtils sInstance = new GCUtils(); + private int mGCTryCount = 0; + + public static GCUtils getInstance() { + return sInstance; + } + + public void reset() { + mGCTryCount = 0; + } + + public boolean tryGCOrWait(String metaData, OutOfMemoryError oome) { + if (LatinImeLogger.sDBG) { + Log.d(TAG, "Encountered Out of memory Error. Try GC."); + } + if (mGCTryCount == 0) { + System.gc(); + } + if (++mGCTryCount > GC_TRY_COUNT) { + LatinImeLogger.logOnException(metaData, oome); + return false; + } else { + try { + Thread.sleep(GC_INTERVAL); + return true; + } catch (InterruptedException e) { + Log.e(TAG, "Sleep was interrupted."); + LatinImeLogger.logOnException(metaData, oome); + return false; + } + } + } + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index 5f07fce4c..3ffbe1ba6 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -37,7 +37,7 @@ import java.util.List; public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "LatinIMELogs"; - private static boolean sDBG = false; + public static boolean sDBG = false; private static boolean sLOGPRINT = false; // SUPPRESS_EXCEPTION should be true when released to public. private static final boolean SUPPRESS_EXCEPTION = true; diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java index 014d773ab..e99977d21 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java @@ -472,10 +472,15 @@ public class LatinKeyboardView extends KeyboardView { @Override public void draw(Canvas c) { - try { - super.draw(c); - } catch (OutOfMemoryError e) { - LatinImeLogger.logOnException("draw in LatinKeybaordView", e); + LatinIMEUtil.GCUtils.getInstance().reset(); + boolean tryGC = true; + for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { + try { + super.draw(c); + tryGC = false; + } catch (OutOfMemoryError e) { + tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait("LatinKeyboardView", e); + } } if (DEBUG_AUTO_PLAY) { if (mPlaying) {