diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin/Utils.java')
-rw-r--r-- | java/src/com/android/inputmethod/latin/Utils.java | 150 |
1 files changed, 136 insertions, 14 deletions
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index e980d3a30..727e3f16d 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -16,13 +16,18 @@ package com.android.inputmethod.latin; +import com.android.inputmethod.keyboard.KeyboardId; + +import android.content.res.Resources; import android.inputmethodservice.InputMethodService; import android.os.AsyncTask; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; +import android.text.InputType; import android.text.format.DateUtils; import android.util.Log; +import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; @@ -41,6 +46,10 @@ public class Utils { private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4; private static boolean DBG = LatinImeLogger.sDBG; + private Utils() { + // Intentional empty constructor for utility class. + } + /** * Cancel an {@link AsyncTask}. * @@ -55,7 +64,7 @@ public class Utils { } public static class GCUtils { - private static final String TAG = "GCUtils"; + private static final String GC_TAG = GCUtils.class.getSimpleName(); 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 greater than GC_TRY_COUNT. @@ -84,7 +93,7 @@ public class Utils { Thread.sleep(GC_INTERVAL); return true; } catch (InterruptedException e) { - Log.e(TAG, "Sleep was interrupted."); + Log.e(GC_TAG, "Sleep was interrupted."); LatinImeLogger.logOnException(metaData, t); return false; } @@ -261,6 +270,19 @@ public class Utils { return dp[sl][tl]; } + // Get the current stack trace + public static String getStackTrace() { + StringBuilder sb = new StringBuilder(); + try { + throw new RuntimeException(); + } catch (RuntimeException e) { + StackTraceElement[] frames = e.getStackTrace(); + // Start at 1 because the first frame is here and we don't care about it + for (int j = 1; j < frames.length; ++j) sb.append(frames[j].toString() + "\n"); + } + return sb.toString(); + } + // In dictionary.cpp, getSuggestion() method, // suggestion scores are computed using the below formula. // original score (called 'frequency') @@ -268,13 +290,22 @@ public class Utils { // (the number of matched characters between typed word and suggested word)) // * (individual word's score which defined in the unigram dictionary, // and this score is defined in range [0, 255].) - // * (when before.length() == after.length(), - // mFullWordMultiplier (this is defined 2)) - // So, maximum original score is pow(2, before.length()) * 255 * 2 - // So, we can normalize original score by dividing this value. + // Then, the following processing is applied. + // - If the dictionary word is matched up to the point of the user entry + // (full match up to min(before.length(), after.length()) + // => Then multiply by FULL_MATCHED_WORDS_PROMOTION_RATE (this is defined 1.2) + // - If the word is a true full match except for differences in accents or + // capitalization, then treat it as if the frequency was 255. + // - If before.length() == after.length() + // => multiply by mFullWordMultiplier (this is defined 2)) + // So, maximum original score is pow(2, min(before.length(), after.length())) * 255 * 2 * 1.2 + // For historical reasons we ignore the 1.2 modifier (because the measure for a good + // autocorrection threshold was done at a time when it didn't exist). This doesn't change + // the result. + // So, we can normalize original score by dividing pow(2, min(b.l(),a.l())) * 255 * 2. private static final int MAX_INITIAL_SCORE = 255; private static final int TYPED_LETTER_MULTIPLIER = 2; - private static final int FULL_WORD_MULTIPLYER = 2; + private static final int FULL_WORD_MULTIPLIER = 2; public static double calcNormalizedScore(CharSequence before, CharSequence after, int score) { final int beforeLength = before.length(); final int afterLength = after.length(); @@ -284,7 +315,7 @@ public class Utils { // correction. final double maximumScore = MAX_INITIAL_SCORE * Math.pow(TYPED_LETTER_MULTIPLIER, Math.min(beforeLength, afterLength)) - * FULL_WORD_MULTIPLYER; + * FULL_WORD_MULTIPLIER; // add a weight based on edit distance. // distance <= max(afterLength, beforeLength) == afterLength, // so, 0 <= distance / afterLength <= 1 @@ -293,7 +324,7 @@ public class Utils { } public static class UsabilityStudyLogUtils { - private static final String TAG = "UsabilityStudyLogUtils"; + private static final String USABILITY_TAG = UsabilityStudyLogUtils.class.getSimpleName(); private static final String FILENAME = "log.txt"; private static final UsabilityStudyLogUtils sInstance = new UsabilityStudyLogUtils(); @@ -330,7 +361,7 @@ public class Utils { try { mWriter = getPrintWriter(mDirectory, FILENAME, false); } catch (IOException e) { - Log.e(TAG, "Can't create log file."); + Log.e(USABILITY_TAG, "Can't create log file."); } } } @@ -367,7 +398,7 @@ public class Utils { final String printString = String.format("%s\t%d\t%s\n", mDateFormat.format(mDate), currentTime, log); if (LatinImeLogger.sDBG) { - Log.d(TAG, "Write: " + log); + Log.d(USABILITY_TAG, "Write: " + log); } mWriter.print(printString); } @@ -388,10 +419,10 @@ public class Utils { sb.append(line); } } catch (IOException e) { - Log.e(TAG, "Can't read log file."); + Log.e(USABILITY_TAG, "Can't read log file."); } finally { if (LatinImeLogger.sDBG) { - Log.d(TAG, "output all logs\n" + sb.toString()); + Log.d(USABILITY_TAG, "output all logs\n" + sb.toString()); } mIms.getCurrentInputConnection().commitText(sb.toString(), 0); try { @@ -410,7 +441,7 @@ public class Utils { public void run() { if (mFile != null && mFile.exists()) { if (LatinImeLogger.sDBG) { - Log.d(TAG, "Delete log file."); + Log.d(USABILITY_TAG, "Delete log file."); } mFile.delete(); mWriter.close(); @@ -439,4 +470,95 @@ public class Utils { return new PrintWriter(new FileOutputStream(mFile), true /* autoFlush */); } } + + public static int getKeyboardMode(EditorInfo attribute) { + if (attribute == null) + return KeyboardId.MODE_TEXT; + + final int inputType = attribute.inputType; + final int variation = inputType & InputType.TYPE_MASK_VARIATION; + + switch (inputType & InputType.TYPE_MASK_CLASS) { + case InputType.TYPE_CLASS_NUMBER: + case InputType.TYPE_CLASS_DATETIME: + return KeyboardId.MODE_NUMBER; + case InputType.TYPE_CLASS_PHONE: + return KeyboardId.MODE_PHONE; + case InputType.TYPE_CLASS_TEXT: + if (Utils.isEmailVariation(variation)) { + return KeyboardId.MODE_EMAIL; + } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { + return KeyboardId.MODE_URL; + } else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) { + return KeyboardId.MODE_IM; + } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { + return KeyboardId.MODE_TEXT; + } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { + return KeyboardId.MODE_WEB; + } else { + return KeyboardId.MODE_TEXT; + } + default: + return KeyboardId.MODE_TEXT; + } + } + + public static boolean isEmailVariation(int variation) { + return variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS + || variation == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS; + } + + // Please refer to TextView.isPasswordInputType + public static boolean isPasswordInputType(int inputType) { + final int variation = + inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION); + return (variation + == (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD)) + || (variation + == (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD)) + || (variation + == (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD)); + } + + // Please refer to TextView.isVisiblePasswordInputType + public static boolean isVisiblePasswordInputType(int inputType) { + final int variation = + inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION); + return variation + == (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); + } + + public static boolean containsInCsv(String key, String csv) { + if (csv == null) + return false; + for (String option : csv.split(",")) { + if (option.equals(key)) + return true; + } + return false; + } + + public static boolean inPrivateImeOptions(String packageName, String key, + EditorInfo attribute) { + if (attribute == null) + return false; + return containsInCsv(packageName != null ? packageName + "." + key : key, + attribute.privateImeOptions); + } + + /** + * Returns a main dictionary resource id + * @return main dictionary resource id + */ + public static int getMainDictionaryResourceId(Resources res) { + return res.getIdentifier("main", "raw", LatinIME.class.getPackage().getName()); + } + + public static void loadNativeLibrary() { + try { + System.loadLibrary("jni_latinime"); + } catch (UnsatisfiedLinkError ule) { + Log.e(TAG, "Could not load native library jni_latinime"); + } + } } |