diff options
| -rw-r--r-- | base/build.gradle | 22 | ||||
| -rw-r--r-- | base/src/main/java/com/anysoftkeyboard/base/utils/GCUtils.java | 62 | ||||
| -rw-r--r-- | jnidictionaryv1/build.gradle | 16 | ||||
| -rw-r--r-- | jnidictionaryv1/src/main/java/com/anysoftkeyboard/dictionaries/jni/BinaryDictionary.java (renamed from src/main/java/com/anysoftkeyboard/dictionaries/jni/BinaryDictionary.java) | 4 | ||||
| -rw-r--r-- | jnidictionaryv2/build.gradle | 16 | ||||
| -rw-r--r-- | jnidictionaryv2/src/main/java/com/anysoftkeyboard/dictionaries/jni/ResourceBinaryDictionary.java (renamed from src/main/java/com/anysoftkeyboard/dictionaries/jni/ResourceBinaryDictionary.java) | 9 | ||||
| -rw-r--r-- | src/main/java/com/anysoftkeyboard/AnySoftKeyboard.java | 4 | ||||
| -rw-r--r-- | src/main/java/com/anysoftkeyboard/keyboards/views/AnyKeyboardBaseView.java | 4 | ||||
| -rw-r--r-- | src/main/java/com/anysoftkeyboard/utils/EditingUtil.java | 336 | ||||
| -rw-r--r-- | src/main/java/com/anysoftkeyboard/utils/IMEUtil.java | 58 |
10 files changed, 88 insertions, 443 deletions
diff --git a/base/build.gradle b/base/build.gradle index e11e5f5cc..d160358bf 100644 --- a/base/build.gradle +++ b/base/build.gradle @@ -1,21 +1,4 @@ -buildscript { - repositories { - mavenLocal() - mavenCentral() - maven { - url 'https://oss.sonatype.org/content/repositories/snapshots/' - } - } - dependencies { - classpath 'com.android.tools.build:gradle:1.2.3' - classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0' - } -} - -apply plugin: 'android-sdk-manager' apply plugin: 'com.android.library' -apply plugin: 'pmd' -apply plugin: 'jacoco' android { compileSdkVersion 22 @@ -27,11 +10,6 @@ android { versionCode 1 versionName "1.0" } - buildTypes { - release { - minifyEnabled false - } - } } dependencies { diff --git a/base/src/main/java/com/anysoftkeyboard/base/utils/GCUtils.java b/base/src/main/java/com/anysoftkeyboard/base/utils/GCUtils.java new file mode 100644 index 000000000..d22c72d4c --- /dev/null +++ b/base/src/main/java/com/anysoftkeyboard/base/utils/GCUtils.java @@ -0,0 +1,62 @@ +package com.anysoftkeyboard.base.utils; + +import android.text.format.DateUtils; +import android.util.Log; + +public class GCUtils { + private 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 greater than GC_TRY_COUNT. + private static final int GC_TRY_LOOP_MAX = 5; + private static final long GC_INTERVAL = DateUtils.SECOND_IN_MILLIS; + private static final GCUtils sInstance = new GCUtils(); + private int mGCTryCount = 0; + + public static GCUtils getInstance() { + return sInstance; + } + + public boolean performOperationWithMemRetry(String TAG, MemRelatedOperation operation, boolean failWithException) { + reset(); + + boolean retry = true; + while (retry) { + try { + operation.operation(); + return true; + } catch (OutOfMemoryError e) { + Log.w(TAG, "WOW! No memory for operation... I'll try to release some."); + retry = tryGCOrWait(TAG, e); + if (!retry && failWithException) throw e; + } + } + return false; + } + + private void reset() { + mGCTryCount = 0; + } + + private boolean tryGCOrWait(String metaData, Throwable t) { + if (mGCTryCount % GC_TRY_COUNT == 0) { + System.gc(); + } + if (mGCTryCount > GC_TRY_LOOP_MAX) { + return false; + } else { + mGCTryCount++; + try { + Thread.sleep(GC_INTERVAL); + return true; + } catch (InterruptedException e) { + Log.e(metaData, "Sleep was interrupted."); + //ImeLogger.logOnException(metaData, t); + return false; + } + } + } + + public interface MemRelatedOperation { + void operation(); + } +} diff --git a/jnidictionaryv1/build.gradle b/jnidictionaryv1/build.gradle index 0c54c90df..8fb981e4e 100644 --- a/jnidictionaryv1/build.gradle +++ b/jnidictionaryv1/build.gradle @@ -1,24 +1,24 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 21 - buildToolsVersion "21.1.2" + compileSdkVersion 22 + buildToolsVersion "22.0.1" defaultConfig { minSdkVersion 7 - targetSdkVersion 21 + targetSdkVersion 22 versionCode 1 versionName "1.0" ndk { moduleName "anysoftkey_jni" } } - buildTypes { - release { - minifyEnabled false - } - } } dependencies { + repositories { + mavenCentral() + } + compile 'net.evendanan.anysoftkeyboard:api:1.2.3' + compile project(':base') } diff --git a/src/main/java/com/anysoftkeyboard/dictionaries/jni/BinaryDictionary.java b/jnidictionaryv1/src/main/java/com/anysoftkeyboard/dictionaries/jni/BinaryDictionary.java index 85b0d2a74..adb9194fd 100644 --- a/src/main/java/com/anysoftkeyboard/dictionaries/jni/BinaryDictionary.java +++ b/jnidictionaryv1/src/main/java/com/anysoftkeyboard/dictionaries/jni/BinaryDictionary.java @@ -17,10 +17,10 @@ package com.anysoftkeyboard.dictionaries.jni; import android.content.res.AssetFileDescriptor; +import android.util.Log; import com.anysoftkeyboard.base.dictionaries.Dictionary; import com.anysoftkeyboard.base.dictionaries.WordComposer; -import com.anysoftkeyboard.utils.Log; import java.io.FileDescriptor; import java.util.Arrays; @@ -65,7 +65,7 @@ public class BinaryDictionary extends Dictionary { try { mNativeDict = 0; long startTime = System.currentTimeMillis(); - mNativeDict = openNative(mAfd.getFileDescriptor(), mAfd.getStartOffset(), mAfd.getLength(), TYPED_LETTER_MULTIPLIER, FULL_WORD_FREQ_MULTIPLIER); + mNativeDict = openNative(mAfd.getFileDescriptor(), mAfd.getStartOffset(), mAfd.getLength(), Dictionary.TYPED_LETTER_MULTIPLIER, Dictionary.FULL_WORD_FREQ_MULTIPLIER); Log.d(TAG, "Loaded dictionary in " + (System.currentTimeMillis() - startTime) + "ms"); } catch (UnsatisfiedLinkError ex) { Log.w(TAG, "Failed to load binary JNI connection! Error: " + ex.getMessage()); diff --git a/jnidictionaryv2/build.gradle b/jnidictionaryv2/build.gradle index 7c6a094ed..7b119490e 100644 --- a/jnidictionaryv2/build.gradle +++ b/jnidictionaryv2/build.gradle @@ -1,24 +1,24 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 21 - buildToolsVersion "21.1.2" + compileSdkVersion 22 + buildToolsVersion "22.0.1" defaultConfig { minSdkVersion 7 - targetSdkVersion 21 + targetSdkVersion 22 versionCode 1 versionName "1.0" ndk { moduleName "anysoftkey2_jni" } } - buildTypes { - release { - minifyEnabled false - } - } } dependencies { + repositories { + mavenCentral() + } + compile 'net.evendanan.anysoftkeyboard:api:1.2.3' + compile project(':base') } diff --git a/src/main/java/com/anysoftkeyboard/dictionaries/jni/ResourceBinaryDictionary.java b/jnidictionaryv2/src/main/java/com/anysoftkeyboard/dictionaries/jni/ResourceBinaryDictionary.java index aac12670c..9983c6c20 100644 --- a/src/main/java/com/anysoftkeyboard/dictionaries/jni/ResourceBinaryDictionary.java +++ b/jnidictionaryv2/src/main/java/com/anysoftkeyboard/dictionaries/jni/ResourceBinaryDictionary.java @@ -19,12 +19,11 @@ package com.anysoftkeyboard.dictionaries.jni; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; +import android.util.Log; import com.anysoftkeyboard.base.dictionaries.Dictionary; import com.anysoftkeyboard.base.dictionaries.WordComposer; -import com.anysoftkeyboard.utils.IMEUtil.GCUtils; -import com.anysoftkeyboard.utils.IMEUtil.GCUtils.MemRelatedOperation; -import com.anysoftkeyboard.utils.Log; +import com.anysoftkeyboard.base.utils.GCUtils; import java.io.IOException; import java.io.InputStream; @@ -114,7 +113,7 @@ public class ResourceBinaryDictionary extends Dictionary { a.recycle(); } - GCUtils.getInstance().performOperationWithMemRetry(TAG, new MemRelatedOperation() { + GCUtils.getInstance().performOperationWithMemRetry(TAG, new GCUtils.MemRelatedOperation() { public void operation() { // The try-catch is for issue 878: // http://code.google.com/p/softkeyboard/issues/detail?id=878 @@ -151,7 +150,7 @@ public class ResourceBinaryDictionary extends Dictionary { if (got != total) { Log.e(TAG, "Read " + got + " bytes, expected " + total); } else { - mNativeDict = openNative(mNativeDictDirectBuffer, TYPED_LETTER_MULTIPLIER, FULL_WORD_FREQ_MULTIPLIER); + mNativeDict = openNative(mNativeDictDirectBuffer, Dictionary.TYPED_LETTER_MULTIPLIER, Dictionary.FULL_WORD_FREQ_MULTIPLIER); mDictLength = total; } } catch (IOException e) { diff --git a/src/main/java/com/anysoftkeyboard/AnySoftKeyboard.java b/src/main/java/com/anysoftkeyboard/AnySoftKeyboard.java index 2eeecf535..e52f94025 100644 --- a/src/main/java/com/anysoftkeyboard/AnySoftKeyboard.java +++ b/src/main/java/com/anysoftkeyboard/AnySoftKeyboard.java @@ -88,8 +88,8 @@ import com.anysoftkeyboard.theme.KeyboardThemeFactory; import com.anysoftkeyboard.ui.VoiceInputNotInstalledActivity; import com.anysoftkeyboard.ui.dev.DeveloperUtils; import com.anysoftkeyboard.ui.settings.MainSettingsActivity; -import com.anysoftkeyboard.utils.IMEUtil.GCUtils; -import com.anysoftkeyboard.utils.IMEUtil.GCUtils.MemRelatedOperation; +import com.anysoftkeyboard.base.utils.GCUtils; +import com.anysoftkeyboard.base.utils.GCUtils.MemRelatedOperation; import com.anysoftkeyboard.utils.Log; import com.anysoftkeyboard.utils.ModifierKeyState; import com.anysoftkeyboard.utils.Workarounds; diff --git a/src/main/java/com/anysoftkeyboard/keyboards/views/AnyKeyboardBaseView.java b/src/main/java/com/anysoftkeyboard/keyboards/views/AnyKeyboardBaseView.java index 7efc5374a..95b8ff0a5 100644 --- a/src/main/java/com/anysoftkeyboard/keyboards/views/AnyKeyboardBaseView.java +++ b/src/main/java/com/anysoftkeyboard/keyboards/views/AnyKeyboardBaseView.java @@ -71,8 +71,8 @@ import com.anysoftkeyboard.quicktextkeys.ui.QuickTextViewFactory; import com.anysoftkeyboard.theme.KeyboardTheme; import com.anysoftkeyboard.theme.KeyboardThemeFactory; import com.anysoftkeyboard.utils.CompatUtils; -import com.anysoftkeyboard.utils.IMEUtil.GCUtils; -import com.anysoftkeyboard.utils.IMEUtil.GCUtils.MemRelatedOperation; +import com.anysoftkeyboard.base.utils.GCUtils; +import com.anysoftkeyboard.base.utils.GCUtils.MemRelatedOperation; import com.anysoftkeyboard.utils.Log; import com.menny.android.anysoftkeyboard.AnyApplication; import com.menny.android.anysoftkeyboard.BuildConfig; diff --git a/src/main/java/com/anysoftkeyboard/utils/EditingUtil.java b/src/main/java/com/anysoftkeyboard/utils/EditingUtil.java deleted file mode 100644 index 77d99507e..000000000 --- a/src/main/java/com/anysoftkeyboard/utils/EditingUtil.java +++ /dev/null @@ -1,336 +0,0 @@ -///* -// * Copyright (C) 2009 Google Inc. -// * -// * 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.anysoftkeyboard.utils; -// -//import android.text.TextUtils; -//import android.view.inputmethod.ExtractedText; -//import android.view.inputmethod.ExtractedTextRequest; -//import android.view.inputmethod.InputConnection; -// -//import java.lang.reflect.InvocationTargetException; -//import java.lang.reflect.Method; -//import java.util.regex.Pattern; -// -///** -// * Utility methods to deal with editing text through an InputConnection. -// */ -//public class EditingUtil { -// /** -// * Number of characters we want to look back in order to identify the previous word -// */ -// private static final int LOOKBACK_CHARACTER_NUM = 15; -// -// // Cache Method pointers -// private static boolean sMethodsInitialized; -// private static Method sMethodGetSelectedText; -// private static Method sMethodSetComposingRegion; -// -// private EditingUtil() {}; -// -// /** -// * Append newText to the text field represented by connection. -// * The new text becomes selected. -// */ -// public static void appendText(InputConnection connection, String newText) { -// if (connection == null) { -// return; -// } -// -// // Commit the composing text -// connection.finishComposingText(); -// -// // Add a space if the field already has text. -// CharSequence charBeforeCursor = connection.getTextBeforeCursor(1, 0); -// if (charBeforeCursor != null -// && !charBeforeCursor.equals(" ") -// && (charBeforeCursor.length() > 0)) { -// newText = " " + newText; -// } -// -// connection.setComposingText(newText, 1); -// } -// -// private static int getCursorPosition(InputConnection connection) { -// ExtractedText extracted = connection.getExtractedText( -// new ExtractedTextRequest(), 0); -// if (extracted == null) { -// return -1; -// } -// return extracted.startOffset + extracted.selectionStart; -// } -// -// /** -// * @param connection connection to the current text field. -// * @param sep characters which may separate words -// * @param range the range object to store the result into -// * @return the word that surrounds the cursor, including up to one trailing -// * separator. For example, if the field contains "he|llo world", where | -// * represents the cursor, then "hello " will be returned. -// */ -// public static String getWordAtCursor( -// InputConnection connection, Range range) { -// Range r = getWordRangeAtCursor(connection, range); -// return (r == null) ? null : r.word; -// } -// -// /** -// * Removes the word surrounding the cursor. Parameters are identical to -// * getWordAtCursor. -// */ -// public static void deleteWordAtCursor(InputConnection connection) { -// -// Range range = getWordRangeAtCursor(connection, null); -// if (range == null) return; -// -// connection.finishComposingText(); -// // Move cursor to beginning of word, to avoid crash when cursor is outside -// // of valid range after deleting text. -// int newCursor = getCursorPosition(connection) - range.charsBefore; -// connection.setSelection(newCursor, newCursor); -// connection.deleteSurroundingText(0, range.charsBefore + range.charsAfter); -// } -// -// /** -// * Represents a range of text, relative to the current cursor position. -// */ -// public static class Range { -// /** Characters before selection start */ -// public int charsBefore; -// -// /** -// * Characters after selection start, including one trailing word -// * separator. -// */ -// public int charsAfter; -// -// /** The actual characters that make up a word */ -// public String word; -// -// public Range() {} -// -// public Range(int charsBefore, int charsAfter, String word) { -// if (charsBefore < 0 || charsAfter < 0) { -// throw new IndexOutOfBoundsException(); -// } -// this.charsBefore = charsBefore; -// this.charsAfter = charsAfter; -// this.word = word; -// } -// } -// -// private static Range getWordRangeAtCursor( -// InputConnection connection, Range range) { -// if (connection == null) { -// return null; -// } -// CharSequence before = connection.getTextBeforeCursor(1000, 0); -// CharSequence after = connection.getTextAfterCursor(1000, 0); -// if (before == null || after == null) { -// return null; -// } -// -// // Find first word separator before the cursor -// int start = before.length(); -// while (start > 0 && !isWhitespace(before.charAt(start - 1))) start--; -// -// // Find last word separator after the cursor -// int end = -1; -// while (++end < after.length() && !isWhitespace(after.charAt(end))); -// -// int cursor = getCursorPosition(connection); -// if (start >= 0 && cursor + end <= after.length() + before.length()) { -// String word = before.toString().substring(start, before.length()) -// + after.toString().substring(0, end); -// -// Range returnRange = range != null? range : new Range(); -// returnRange.charsBefore = before.length() - start; -// returnRange.charsAfter = end; -// returnRange.word = word; -// return returnRange; -// } -// -// return null; -// } -// -// private static boolean isWhitespace(int code) { -// //return whitespace.contains(String.valueOf((char) code)); -// return !Character.isLetter((char)code); -// } -// -// private static final Pattern spaceRegex = Pattern.compile("\\s+"); -// -// public static CharSequence getPreviousWord(InputConnection connection, -// String sentenceSeperators) { -// //TODO: Should fix this. This could be slow! -// CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); -// if (prev == null) { -// return null; -// } -// String[] w = spaceRegex.split(prev); -// if (w.length >= 2 && w[w.length-2].length() > 0) { -// char lastChar = w[w.length-2].charAt(w[w.length-2].length() -1); -// if (sentenceSeperators.contains(String.valueOf(lastChar))) { -// return null; -// } -// return w[w.length-2]; -// } else { -// return null; -// } -// } -// -// public static class SelectedWord { -// public int start; -// public int end; -// public CharSequence word; -// } -// -// /** -// * Takes a character sequence with a single character and checks if the character occurs -// * in a list of word separators or is empty. -// * @param singleChar A CharSequence with null, zero or one character -// * @param wordSeparators A String containing the word separators -// * @return true if the character is at a word boundary, false otherwise -// */ -// private static boolean isWordBoundary(CharSequence singleChar) { -// return TextUtils.isEmpty(singleChar) || isWhitespace(singleChar.charAt(0)); -// } -// -// /** -// * Checks if the cursor is inside a word or the current selection is a whole word. -// * @param ic the InputConnection for accessing the text field -// * @param selStart the start position of the selection within the text field -// * @param selEnd the end position of the selection within the text field. This could be -// * the same as selStart, if there's no selection. -// * @param wordSeparators the word separator characters for the current language -// * @return an object containing the text and coordinates of the selected/touching word, -// * null if the selection/cursor is not marking a whole word. -// */ -// public static SelectedWord getWordAtCursorOrSelection(final InputConnection ic, int selStart, int selEnd) { -// if (selStart == selEnd) { -// // There is just a cursor, so get the word at the cursor -// EditingUtil.Range range = new EditingUtil.Range(); -// CharSequence touching = getWordAtCursor(ic, range); -// if (!TextUtils.isEmpty(touching)) { -// SelectedWord selWord = new SelectedWord(); -// selWord.word = touching; -// selWord.start = selStart - range.charsBefore; -// selWord.end = selEnd + range.charsAfter; -// return selWord; -// } -// } else { -// // Is the previous character empty or a word separator? If not, return null. -// CharSequence charsBefore = ic.getTextBeforeCursor(1, 0); -// if (!isWordBoundary(charsBefore)) { -// return null; -// } -// -// // Is the next character empty or a word separator? If not, return null. -// CharSequence charsAfter = ic.getTextAfterCursor(1, 0); -// if (!isWordBoundary(charsAfter)) { -// return null; -// } -// -// // Extract the selection alone -// CharSequence touching = getSelectedText(ic, selStart, selEnd); -// if (TextUtils.isEmpty(touching)) return null; -// // Is any part of the selection a separator? If so, return null. -// final int length = touching.length(); -// for (int i = 0; i < length; i++) { -// if (isWhitespace(touching.subSequence(i, i + 1).charAt(0))) { -// return null; -// } -// } -// // Prepare the selected word -// SelectedWord selWord = new SelectedWord(); -// selWord.start = selStart; -// selWord.end = selEnd; -// selWord.word = touching; -// return selWord; -// } -// return null; -// } -// -//// /** -//// * Cache method pointers for performance -//// */ -//// private static void initializeMethodsForReflection() { -//// try { -//// // These will either both exist or not, so no need for separate try/catch blocks. -//// // If other methods are added later, use separate try/catch blocks. -//// sMethodGetSelectedText = InputConnection.class.getMethod("getSelectedText", int.class); -//// sMethodSetComposingRegion = InputConnection.class.getMethod("setComposingRegion", -//// int.class, int.class); -//// } catch (NoSuchMethodException exc) { -//// // Ignore -//// } -//// sMethodsInitialized = true; -//// } -//// -//// /** -//// * Returns the selected text between the selStart and selEnd positions. -//// */ -//// private static CharSequence getSelectedText(InputConnection ic, int selStart, int selEnd) { -//// // Use reflection, for backward compatibility -//// CharSequence result = null; -//// if (!sMethodsInitialized) { -//// initializeMethodsForReflection(); -//// } -//// if (sMethodGetSelectedText != null) { -//// try { -//// result = (CharSequence) sMethodGetSelectedText.invoke(ic, 0); -//// return result; -//// } catch (InvocationTargetException exc) { -//// // Ignore -//// } catch (IllegalArgumentException e) { -//// // Ignore -//// } catch (IllegalAccessException e) { -//// // Ignore -//// } -//// } -//// // Reflection didn't work, try it the poor way, by moving the cursor to the start, -//// // getting the text after the cursor and moving the text back to selected mode. -//// // TODO: Verify that this works properly in conjunction with -//// // LatinIME#onUpdateSelection -//// ic.setSelection(selStart, selEnd); -//// result = ic.getTextAfterCursor(selEnd - selStart, 0); -//// ic.setSelection(selStart, selEnd); -//// return result; -//// } -// -//// /** -//// * Tries to set the text into composition mode if there is support for it in the framework. -//// */ -//// public static void underlineWord(InputConnection ic, SelectedWord word) { -//// // Use reflection, for backward compatibility -//// // If method not found, there's nothing we can do. It still works but just wont underline -//// // the word. -//// if (!sMethodsInitialized) { -//// initializeMethodsForReflection(); -//// } -//// if (sMethodSetComposingRegion != null) { -//// try { -//// sMethodSetComposingRegion.invoke(ic, word.start, word.end); -//// } catch (InvocationTargetException exc) { -//// // Ignore -//// } catch (IllegalArgumentException e) { -//// // Ignore -//// } catch (IllegalAccessException e) { -//// // Ignore -//// } -//// } -//// } -//}
\ No newline at end of file diff --git a/src/main/java/com/anysoftkeyboard/utils/IMEUtil.java b/src/main/java/com/anysoftkeyboard/utils/IMEUtil.java index c0bf46253..5ad9cb280 100644 --- a/src/main/java/com/anysoftkeyboard/utils/IMEUtil.java +++ b/src/main/java/com/anysoftkeyboard/utils/IMEUtil.java @@ -175,64 +175,6 @@ public class IMEUtil { }*/ } - public static class GCUtils { - private 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 greater than GC_TRY_COUNT. - private 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 boolean performOperationWithMemRetry(String TAG, MemRelatedOperation operation, boolean failWithException) { - reset(); - - boolean retry = true; - while (retry) { - try { - operation.operation(); - return true; - } catch (OutOfMemoryError e) { - Log.w(TAG, "WOW! No memory for operation... I'll try to release some."); - retry = tryGCOrWait(TAG, e); - if (!retry && failWithException) throw e; - } - } - return false; - } - - private void reset() { - mGCTryCount = 0; - } - - private boolean tryGCOrWait(String metaData, Throwable t) { - if (mGCTryCount % GC_TRY_COUNT == 0) { - System.gc(); - } - if (mGCTryCount > GC_TRY_LOOP_MAX) { - return false; - } else { - mGCTryCount++; - try { - Thread.sleep(GC_INTERVAL); - return true; - } catch (InterruptedException e) { - Log.e(metaData, "Sleep was interrupted."); - //ImeLogger.logOnException(metaData, t); - return false; - } - } - } - - public static interface MemRelatedOperation { - void operation(); - } - } - /* package */ static class RingCharBuffer { /* package */ static final int BUFSIZE = 20; private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC'; |
