diff options
Diffstat (limited to 'java/src')
4 files changed, 74 insertions, 64 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index b8aab4cdf..8a5fc495e 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1002,8 +1002,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } // This will reset the whole input state to the starting state. It will clear - // the composing word, reset the last composed word, tell the inputconnection - // and the composingStateManager about it. + // the composing word, reset the last composed word, tell the inputconnection about it. private void resetEntireInputState() { resetComposingState(true /* alsoResetLastComposedWord */); updateSuggestions(); @@ -1958,7 +1957,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // expect to receive non-words. if (!mCurrentSettings.mCorrectionEnabled) return null; - if (mUserHistoryDictionary != null) { + final UserHistoryDictionary userHistoryDictionary = mUserHistoryDictionary; + if (userHistoryDictionary != null) { final CharSequence prevWord = mConnection.getPreviousWord(mCurrentSettings.mWordSeparators); final String secondWord; @@ -1973,7 +1973,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final int maxFreq = AutoCorrection.getMaxFrequency( mSuggest.getUnigramDictionaries(), suggestion); if (maxFreq == 0) return null; - mUserHistoryDictionary.addToUserHistory(null == prevWord ? null : prevWord.toString(), + userHistoryDictionary.addToUserHistory(null == prevWord ? null : prevWord.toString(), secondWord, maxFreq > 0); return prevWord; } diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index ee596924f..cf3cc7873 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -379,29 +379,43 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mCurrentLogUnit.addLogAtom(keys, values, false); } - private boolean isInDictionary(CharSequence word) { - return (mDictionary != null) && (mDictionary.isValidWord(word)); + /* package for test */ boolean isPrivacyThreat(String word) { + // currently: word not in dictionary or contains numbers. + if (TextUtils.isEmpty(word)) { + return false; + } + final int length = word.length(); + boolean hasLetter = false; + for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) { + final int codePoint = Character.codePointAt(word, i); + if (Character.isDigit(codePoint)) { + return true; + } + if (Character.isLetter(codePoint)) { + hasLetter = true; + break; // Word may contain digits, but will only be allowed if in the dictionary. + } + } + if (hasLetter) { + if (mDictionary == null && mSuggest != null && mSuggest.hasMainDictionary()) { + mDictionary = mSuggest.getMainDictionary(); + } + if (mDictionary == null) { + // Can't access dictionary. Assume privacy threat. + return true; + } + return !(mDictionary.isValidWord(word)); + } + // No letters, no numbers. Punctuation, space, or something else. + return false; } /** - * Write out enqueued LogEvents to the log, filtered for privacy. - * - * If word is in the dictionary, then it is not privacy-sensitive and all LogEvents related to - * it can be written to the log. If the word is not in the dictionary, then it may correspond - * to a proper name, which might reveal private information, so neither the word nor any - * information related to the word (e.g. the down/motion/up coordinates) should be revealed. - * These LogEvents have been marked as privacy-sensitive; non privacy-sensitive events are still - * written out. - * - * @param word the word to be checked for inclusion in the dictionary + * Write out enqueued LogEvents to the log, possibly dropping privacy sensitive events. */ - /* package for test */ synchronized void flushQueue(CharSequence word) { + /* package for test */ synchronized void flushQueue(boolean removePotentiallyPrivateEvents) { if (isAllowedToLog()) { - // check for dictionary - if (mDictionary == null && mSuggest != null && mSuggest.hasMainDictionary()) { - mDictionary = mSuggest.getMainDictionary(); - } - mCurrentLogUnit.setIsPrivacySafe(word != null && isInDictionary(word)); + mCurrentLogUnit.setRemovePotentiallyPrivateEvents(removePotentiallyPrivateEvents); mLoggingHandler.post(mCurrentLogUnit); mCurrentLogUnit = new LogUnit(); } @@ -513,7 +527,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private final List<String[]> mKeysList = new ArrayList<String[]>(); private final List<Object[]> mValuesList = new ArrayList<Object[]>(); private final List<Boolean> mIsPotentiallyPrivate = new ArrayList<Boolean>(); - private boolean mIsPrivacySafe = false; + private boolean mRemovePotentiallyPrivateEvents = true; private void addLogAtom(final String[] keys, final Object[] values, final Boolean isPotentiallyPrivate) { @@ -522,15 +536,15 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mIsPotentiallyPrivate.add(isPotentiallyPrivate); } - void setIsPrivacySafe(boolean isPrivacySafe) { - mIsPrivacySafe = isPrivacySafe; + void setRemovePotentiallyPrivateEvents(boolean removePotentiallyPrivateEvents) { + mRemovePotentiallyPrivateEvents = removePotentiallyPrivateEvents; } @Override public void run() { final int numAtoms = mKeysList.size(); for (int atomIndex = 0; atomIndex < numAtoms; atomIndex++) { - if (!mIsPrivacySafe && mIsPotentiallyPrivate.get(atomIndex)) { + if (mRemovePotentiallyPrivateEvents && mIsPotentiallyPrivate.get(atomIndex)) { continue; } final String[] keys = mKeysList.get(atomIndex); @@ -548,7 +562,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang StringBuilder sb = null; final int length = s.length(); for (int i = 0; i < length; i = s.offsetByCodePoints(i, 1)) { - int codePoint = Character.codePointAt(s, i); + final int codePoint = Character.codePointAt(s, i); if (Character.isDigit(codePoint)) { if (sb == null) { sb = new StringBuilder(length); @@ -638,19 +652,20 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent( EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values); - researchLogger.flushQueue(autoCorrection); + researchLogger.flushQueue(researchLogger.isPrivacyThreat(autoCorrection)); } private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = { "LatinIMECommitText", "typedWord" }; public static void latinIME_commitText(final CharSequence typedWord) { + final String scrubbedWord = scrubDigitsFromString(typedWord.toString()); final Object[] values = { - scrubDigitsFromString(typedWord.toString()) + scrubbedWord }; final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_COMMITTEXT, values); - researchLogger.flushQueue(typedWord); + researchLogger.flushQueue(researchLogger.isPrivacyThreat(scrubbedWord)); } private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = { @@ -728,7 +743,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } final ResearchLogger researchLogger = getInstance(); researchLogger.enqueueEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values); - researchLogger.flushQueue(null); + researchLogger.flushQueue(true); // Play it safe. Remove privacy-sensitive events. } } @@ -809,7 +824,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent( EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values); - researchLogger.flushQueue(cs.toString()); + researchLogger.flushQueue(researchLogger.isPrivacyThreat(cs.toString())); } private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = { @@ -824,7 +839,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang final ResearchLogger researchLogger = getInstance(); researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY, values); - researchLogger.flushQueue(suggestion.toString()); + researchLogger.flushQueue(researchLogger.isPrivacyThreat(suggestion.toString())); } private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = { diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 152d66851..4c67b4957 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -69,9 +69,7 @@ public class Settings extends InputMethodSettingsFragment public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY = "pref_key_preview_popup_dismiss_delay"; public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict"; - public static final String PREF_BIGRAM_SUGGESTION = "next_word_suggestion"; public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction"; - public static final String PREF_KEY_ENABLE_SPAN_INSERT = "enable_span_insert"; public static final String PREF_VIBRATION_DURATION_SETTINGS = "pref_vibration_duration_settings"; public static final String PREF_KEYPRESS_SOUND_VOLUME = @@ -87,9 +85,7 @@ public class Settings extends InputMethodSettingsFragment private ListPreference mShowCorrectionSuggestionsPreference; private ListPreference mAutoCorrectionThresholdPreference; private ListPreference mKeyPreviewPopupDismissDelay; - // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary - private CheckBoxPreference mBigramSuggestion; - // Prediction: use bigrams to predict the next word when there is no input for it yet + // Use bigrams to predict the next word when there is no input for it yet private CheckBoxPreference mBigramPrediction; private Preference mDebugSettingsPreference; @@ -100,7 +96,6 @@ public class Settings extends InputMethodSettingsFragment final String autoCorrectionOff = getResources().getString( R.string.auto_correction_threshold_mode_index_off); final String currentSetting = mAutoCorrectionThresholdPreference.getValue(); - mBigramSuggestion.setEnabled(!currentSetting.equals(autoCorrectionOff)); if (null != mBigramPrediction) { mBigramPrediction.setEnabled(!currentSetting.equals(autoCorrectionOff)); } @@ -124,7 +119,6 @@ public class Settings extends InputMethodSettingsFragment mAutoCorrectionThresholdPreference = (ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD); - mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTION); mBigramPrediction = (CheckBoxPreference) findPreference(PREF_BIGRAM_PREDICTIONS); mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS); if (mDebugSettingsPreference != null) { @@ -149,12 +143,9 @@ public class Settings extends InputMethodSettingsFragment generalSettings.removePreference(mVoicePreference); } - final PreferenceGroup advancedSettings = - (PreferenceGroup) findPreference(PREF_ADVANCED_SETTINGS); - // Remove those meaningless options for now. TODO: delete them for good - advancedSettings.removePreference(findPreference(PREF_BIGRAM_SUGGESTION)); - advancedSettings.removePreference(findPreference(PREF_KEY_ENABLE_SPAN_INSERT)); if (!VibratorUtils.getInstance(context).hasVibrator()) { + final PreferenceGroup advancedSettings = + (PreferenceGroup) findPreference(PREF_ADVANCED_SETTINGS); generalSettings.removePreference(findPreference(PREF_VIBRATE_ON)); if (null != advancedSettings) { // Theoretically advancedSettings cannot be null advancedSettings.removePreference(findPreference(PREF_VIBRATION_DURATION_SETTINGS)); @@ -167,15 +158,6 @@ public class Settings extends InputMethodSettingsFragment generalSettings.removePreference(findPreference(PREF_POPUP_ON)); } - final boolean showBigramSuggestionsOption = res.getBoolean( - R.bool.config_enable_next_word_suggestions_option); - if (!showBigramSuggestionsOption) { - textCorrectionGroup.removePreference(mBigramSuggestion); - if (null != mBigramPrediction) { - textCorrectionGroup.removePreference(mBigramPrediction); - } - } - final CheckBoxPreference includeOtherImesInLanguageSwitchList = (CheckBoxPreference)findPreference(PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST); includeOtherImesInLanguageSwitchList.setEnabled( diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java index 6fa1a25a1..5bcdb57b5 100644 --- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java @@ -36,11 +36,22 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { // TODO: use Words.SHORTCUT when it's public in the SDK final static String SHORTCUT = "shortcut"; - private static final String[] PROJECTION_QUERY = { - Words.WORD, - SHORTCUT, - Words.FREQUENCY, - }; + private static final String[] PROJECTION_QUERY; + static { + // 16 is JellyBean, but we want this to compile against ICS. + if (android.os.Build.VERSION.SDK_INT >= 16) { + PROJECTION_QUERY = new String[] { + Words.WORD, + SHORTCUT, + Words.FREQUENCY, + }; + } else { + PROJECTION_QUERY = new String[] { + Words.WORD, + Words.FREQUENCY, + }; + } + } private static final String NAME = "userunigram"; @@ -136,7 +147,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { requestArguments = localeElements; } final Cursor cursor = mContext.getContentResolver().query( - Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), requestArguments, null); + Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), requestArguments, null); try { addWords(cursor); } finally { @@ -182,16 +193,18 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { } private void addWords(Cursor cursor) { + // 16 is JellyBean, but we want this to compile against ICS. + final boolean hasShortcutColumn = android.os.Build.VERSION.SDK_INT >= 16; clearFusionDictionary(); if (cursor == null) return; if (cursor.moveToFirst()) { final int indexWord = cursor.getColumnIndex(Words.WORD); - final int indexShortcut = cursor.getColumnIndex(SHORTCUT); + final int indexShortcut = hasShortcutColumn ? cursor.getColumnIndex(SHORTCUT) : 0; final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY); while (!cursor.isAfterLast()) { - String word = cursor.getString(indexWord); - String shortcut = cursor.getString(indexShortcut); - int frequency = cursor.getInt(indexFrequency); + final String word = cursor.getString(indexWord); + final String shortcut = hasShortcutColumn ? cursor.getString(indexShortcut) : null; + final int frequency = cursor.getInt(indexFrequency); // Safeguard against adding really long words. if (word.length() < MAX_WORD_LENGTH) { super.addWord(word, null, frequency); |