diff options
Diffstat (limited to 'java/src')
18 files changed, 538 insertions, 106 deletions
diff --git a/java/src/com/android/inputmethod/latin/AutoDictionary.java b/java/src/com/android/inputmethod/latin/AutoDictionary.java index da9dd6eb9..93f1985ca 100644 --- a/java/src/com/android/inputmethod/latin/AutoDictionary.java +++ b/java/src/com/android/inputmethod/latin/AutoDictionary.java @@ -17,6 +17,8 @@ package com.android.inputmethod.latin; import java.util.HashMap; +import java.util.Set; +import java.util.Map.Entry; import android.content.ContentValues; import android.content.Context; @@ -24,8 +26,8 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; +import android.os.AsyncTask; import android.provider.BaseColumns; -import android.provider.UserDictionary.Words; import android.util.Log; /** @@ -51,6 +53,9 @@ public class AutoDictionary extends ExpandableDictionary { // Locale for which this auto dictionary is storing words private String mLocale; + private HashMap<String,Integer> mPendingWrites = new HashMap<String,Integer>(); + private final Object mPendingWritesLock = new Object(); + private static final String DATABASE_NAME = "auto_dict.db"; private static final int DATABASE_VERSION = 1; @@ -78,13 +83,15 @@ public class AutoDictionary extends ExpandableDictionary { sDictProjectionMap.put(COLUMN_LOCALE, COLUMN_LOCALE); } - private DatabaseHelper mOpenHelper; + private static DatabaseHelper mOpenHelper = null; public AutoDictionary(Context context, LatinIME ime, String locale) { super(context); mIme = ime; mLocale = locale; - mOpenHelper = new DatabaseHelper(getContext()); + if (mOpenHelper == null) { + mOpenHelper = new DatabaseHelper(getContext()); + } if (mLocale != null && mLocale.length() > 1) { loadDictionary(); } @@ -98,7 +105,11 @@ public class AutoDictionary extends ExpandableDictionary { @Override public void close() { - mOpenHelper.close(); + flushPendingWrites(); + // Don't close the database as locale changes will require it to be reopened anyway + // Also, the database is written to somewhat frequently, so it needs to be kept alive + // throughout the life of the process. + // mOpenHelper.close(); super.close(); } @@ -106,21 +117,24 @@ public class AutoDictionary extends ExpandableDictionary { public void loadDictionaryAsync() { // Load the words that correspond to the current input locale Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale }); - if (cursor.moveToFirst()) { - int wordIndex = cursor.getColumnIndex(COLUMN_WORD); - int frequencyIndex = cursor.getColumnIndex(COLUMN_FREQUENCY); - while (!cursor.isAfterLast()) { - String word = cursor.getString(wordIndex); - int frequency = cursor.getInt(frequencyIndex); - // Safeguard against adding really long words. Stack may overflow due - // to recursive lookup - if (word.length() < getMaxWordLength()) { - super.addWord(word, frequency); + try { + if (cursor.moveToFirst()) { + int wordIndex = cursor.getColumnIndex(COLUMN_WORD); + int frequencyIndex = cursor.getColumnIndex(COLUMN_FREQUENCY); + while (!cursor.isAfterLast()) { + String word = cursor.getString(wordIndex); + int frequency = cursor.getInt(frequencyIndex); + // Safeguard against adding really long words. Stack may overflow due + // to recursive lookup + if (word.length() < getMaxWordLength()) { + super.addWord(word, frequency); + } + cursor.moveToNext(); } - cursor.moveToNext(); } + } finally { + cursor.close(); } - cursor.close(); } @Override @@ -135,14 +149,29 @@ public class AutoDictionary extends ExpandableDictionary { int freq = getWordFrequency(word); freq = freq < 0 ? addFrequency : freq + addFrequency; super.addWord(word, freq); + if (freq >= PROMOTION_THRESHOLD) { mIme.promoteToUserDictionary(word, FREQUENCY_FOR_AUTO_ADD); - // Delete the word (for input locale) from the auto dictionary db, as it - // is now in the user dictionary provider. - delete(COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?", - new String[] { word, mLocale }); - } else { - update(word, freq, mLocale); + freq = 0; + } + + synchronized (mPendingWritesLock) { + // Write a null frequency if it is to be deleted from the db + mPendingWrites.put(word, freq == 0 ? null : new Integer(freq)); + } + } + + /** + * Schedules a background thread to write any pending words to the database. + */ + public void flushPendingWrites() { + synchronized (mPendingWritesLock) { + // Nothing pending? Return + if (mPendingWrites.isEmpty()) return; + // Create a background thread to write the pending entries + new UpdateDbTask(getContext(), mOpenHelper, mPendingWrites, mLocale).execute(); + // Create a new map for writing new entries into while the old one is written to db + mPendingWrites = new HashMap<String, Integer>(); } } @@ -186,26 +215,45 @@ public class AutoDictionary extends ExpandableDictionary { return c; } - private int delete(String where, String[] whereArgs) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - int count = db.delete(AUTODICT_TABLE_NAME, where, whereArgs); - return count; - } + /** + * Async task to write pending words to the database so that it stays in sync with + * the in-memory trie. + */ + private static class UpdateDbTask extends AsyncTask<Void, Void, Void> { + private final HashMap<String, Integer> mMap; + private final DatabaseHelper mDbHelper; + private final String mLocale; - private int update(String word, int frequency, String locale) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - long count = db.delete(AUTODICT_TABLE_NAME, COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?", - new String[] { word, locale }); - count = db.insert(AUTODICT_TABLE_NAME, null, - getContentValues(word, frequency, locale)); - return (int) count; - } + public UpdateDbTask(Context context, DatabaseHelper openHelper, + HashMap<String, Integer> pendingWrites, String locale) { + mMap = pendingWrites; + mLocale = locale; + mDbHelper = openHelper; + } + + @Override + protected Void doInBackground(Void... v) { + SQLiteDatabase db = mDbHelper.getWritableDatabase(); + // Write all the entries to the db + Set<Entry<String,Integer>> mEntries = mMap.entrySet(); + for (Entry<String,Integer> entry : mEntries) { + Integer freq = entry.getValue(); + db.delete(AUTODICT_TABLE_NAME, COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?", + new String[] { entry.getKey(), mLocale }); + if (freq != null) { + db.insert(AUTODICT_TABLE_NAME, null, + getContentValues(entry.getKey(), freq, mLocale)); + } + } + return null; + } - private ContentValues getContentValues(String word, int frequency, String locale) { - ContentValues values = new ContentValues(4); - values.put(COLUMN_WORD, word); - values.put(COLUMN_FREQUENCY, frequency); - values.put(COLUMN_LOCALE, locale); - return values; + private ContentValues getContentValues(String word, int frequency, String locale) { + ContentValues values = new ContentValues(4); + values.put(COLUMN_WORD, word); + values.put(COLUMN_FREQUENCY, frequency); + values.put(COLUMN_LOCALE, locale); + return values; + } } } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 43f4c4cb6..87de94b76 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2008 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 diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java index 0c0373b3b..3a199bbaf 100755 --- a/java/src/com/android/inputmethod/latin/CandidateView.java +++ b/java/src/com/android/inputmethod/latin/CandidateView.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2008 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 diff --git a/java/src/com/android/inputmethod/latin/CandidateViewContainer.java b/java/src/com/android/inputmethod/latin/CandidateViewContainer.java index e13f2738c..e0cb8c3b0 100644 --- a/java/src/com/android/inputmethod/latin/CandidateViewContainer.java +++ b/java/src/com/android/inputmethod/latin/CandidateViewContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2008 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 diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index b656d04dc..e7b526663 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2008 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 diff --git a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java index b1ddb2175..b5a11010b 100644 --- a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java +++ b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java @@ -23,6 +23,8 @@ import java.util.Locale; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; +import android.content.res.Configuration; +import android.content.res.Resources; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.PreferenceActivity; @@ -35,7 +37,7 @@ public class InputLanguageSelection extends PreferenceActivity { private String mSelectedLanguages; private ArrayList<Loc> mAvailableLanguages = new ArrayList<Loc>(); private static final String[] BLACKLIST_LANGUAGES = { - "ko", "ja", "zh" + "ko", "ja", "zh", "el" }; private static class Loc implements Comparable { @@ -75,6 +77,9 @@ public class InputLanguageSelection extends PreferenceActivity { pref.setTitle(LanguageSwitcher.toTitleCase(locale.getDisplayName(locale))); boolean checked = isLocaleIn(locale, languageList); pref.setChecked(checked); + if (hasDictionary(locale)) { + pref.setSummary(R.string.has_dictionary); + } parent.addPreference(pref); } } @@ -92,6 +97,25 @@ public class InputLanguageSelection extends PreferenceActivity { return false; } + private boolean hasDictionary(Locale locale) { + Resources res = getResources(); + Configuration conf = res.getConfiguration(); + Locale saveLocale = conf.locale; + boolean haveDictionary = false; + conf.locale = locale; + res.updateConfiguration(conf, res.getDisplayMetrics()); + BinaryDictionary bd = new BinaryDictionary(this, R.raw.main); + // Is the dictionary larger than a placeholder? Arbitrarily chose a lower limit of + // 4000-5000 words, whereas the LARGE_DICTIONARY is about 20000+ words. + if (bd.getSize() > Suggest.LARGE_DICTIONARY_THRESHOLD / 4) { + haveDictionary = true; + } + bd.close(); + conf.locale = saveLocale; + res.updateConfiguration(conf, res.getDisplayMetrics()); + return haveDictionary; + } + private String get5Code(Locale locale) { String country = locale.getCountry(); return locale.getLanguage() diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index 438680cf8..1a196448f 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Google Inc. + * Copyright (C) 2008 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 diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index ffa7b0a4b..d0baed52a 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1,6 +1,6 @@ /* - * Copyright (C) 2008-2009 Google Inc. - * + * Copyright (C) 2008 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 @@ -39,7 +39,7 @@ import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.preference.PreferenceManager; -import android.speech.RecognitionManager; +import android.speech.SpeechRecognizer; import android.text.AutoText; import android.text.ClipboardManager; import android.text.TextUtils; @@ -158,7 +158,7 @@ public class LatinIME extends InputMethodService private UserDictionary mUserDictionary; private ContactsDictionary mContactsDictionary; - private ExpandableDictionary mAutoDictionary; + private AutoDictionary mAutoDictionary; private Hints mHints; @@ -226,6 +226,9 @@ public class LatinIME extends InputMethodService private long mSwipeTriggerTimeMillis; private boolean mConfigurationChanging; + // Keeps track of most recently inserted text (multi-character key) for reverting + private CharSequence mEnteredText; + // For each word, a list of potential replacements, usually from voice. private Map<String, List<CharSequence>> mWordToSuggestions = new HashMap<String, List<CharSequence>>(); @@ -234,6 +237,7 @@ public class LatinIME extends InputMethodService List<String> candidates; Map<String, List<CharSequence>> alternatives; } + private boolean mRefreshKeyboardRequired; Handler mHandler = new Handler() { @@ -451,6 +455,8 @@ public class LatinIME extends InputMethodService mCompletions = null; mCapsLock = false; mEmailText = false; + mEnteredText = null; + switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) { case EditorInfo.TYPE_CLASS_NUMBER: case EditorInfo.TYPE_CLASS_DATETIME: @@ -552,6 +558,7 @@ public class LatinIME extends InputMethodService if (VOICE_INSTALLED && !mConfigurationChanging) { if (mAfterVoiceInput) { + mVoiceInput.flushAllTextModificationCounters(); mVoiceInput.logInputEnded(); } mVoiceInput.flushLogs(); @@ -560,6 +567,7 @@ public class LatinIME extends InputMethodService if (mInputView != null) { mInputView.closing(); } + if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites(); } @Override @@ -567,8 +575,6 @@ public class LatinIME extends InputMethodService super.onUpdateExtractedText(token, text); InputConnection ic = getCurrentInputConnection(); if (!mImmediatelyAfterVoiceInput && mAfterVoiceInput && ic != null) { - mVoiceInput.logTextModified(); - if (mHints.showPunctuationHintIfNecessary(ic)) { mVoiceInput.logPunctuationHintDisplayed(); } @@ -592,6 +598,11 @@ public class LatinIME extends InputMethodService + ", ce=" + candidatesEnd); } + if (mAfterVoiceInput) { + mVoiceInput.setCursorPos(newSelEnd); + mVoiceInput.setSelectionSpan(newSelEnd - newSelStart); + } + mSuggestionShouldReplaceCurrentWord = false; // If the current selection in the text view changes, we should // clear whatever candidate text we have. @@ -975,6 +986,8 @@ public class LatinIME extends InputMethodService if (mKeyboardSwitcher.onKey(primaryCode)) { changeKeyboardMode(); } + // Reset after any single keystroke + mEnteredText = null; } public void onText(CharSequence text) { @@ -993,16 +1006,32 @@ public class LatinIME extends InputMethodService updateShiftKeyState(getCurrentInputEditorInfo()); mJustRevertedSeparator = null; mJustAddedAutoSpace = false; + mEnteredText = text; } private void handleBackspace() { if (VOICE_INSTALLED && mVoiceInputHighlighted) { + mVoiceInput.incrementTextModificationDeleteCount( + mVoiceResults.candidates.get(0).toString().length()); revertVoiceInput(); return; } boolean deleteChar = false; InputConnection ic = getCurrentInputConnection(); if (ic == null) return; + + if (mAfterVoiceInput) { + // Don't log delete if the user is pressing delete at + // the beginning of the text box (hence not deleting anything) + if (mVoiceInput.getCursorPos() > 0) { + // If anything was selected before the delete was pressed, increment the + // delete count by the length of the selection + int deleteLen = mVoiceInput.getSelectionSpan() > 0 ? + mVoiceInput.getSelectionSpan() : 1; + mVoiceInput.incrementTextModificationDeleteCount(deleteLen); + } + } + if (mPredicting) { final int length = mComposing.length(); if (length > 0) { @@ -1024,6 +1053,8 @@ public class LatinIME extends InputMethodService if (TextEntryState.getState() == TextEntryState.STATE_UNDO_COMMIT) { revertLastWord(deleteChar); return; + } else if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { + ic.deleteSurroundingText(mEnteredText.length(), 0); } else if (deleteChar) { sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); if (mDeleteCount > DELETE_ACCELERATE_AT) { @@ -1048,6 +1079,12 @@ public class LatinIME extends InputMethodService if (VOICE_INSTALLED && mVoiceInputHighlighted) { commitVoiceInput(); } + + if (mAfterVoiceInput) { + // Assume input length is 1. This assumption fails for smiley face insertions. + mVoiceInput.incrementTextModificationInsertCount(1); + } + if (isAlphabet(primaryCode) && isPredictionOn() && !isCursorTouchingWord()) { if (!mPredicting) { mPredicting = true; @@ -1091,6 +1128,12 @@ public class LatinIME extends InputMethodService if (VOICE_INSTALLED && mVoiceInputHighlighted) { commitVoiceInput(); } + + if (mAfterVoiceInput){ + // Assume input length is 1. This assumption fails for smiley face insertions. + mVoiceInput.incrementTextModificationInsertPunctuationCount(1); + } + boolean pickedDefault = false; // Handle separator InputConnection ic = getCurrentInputConnection(); @@ -1344,7 +1387,7 @@ public class LatinIME extends InputMethodService String bestResult = nBest.get(0).toString(); - mVoiceInput.logVoiceInputDelivered(); + mVoiceInput.logVoiceInputDelivered(bestResult.length()); mHints.registerVoiceResult(bestResult); @@ -1405,7 +1448,7 @@ public class LatinIME extends InputMethodService ((LatinKeyboard) mInputView.getKeyboard()).setPreferredLetters(nextLettersFrequencies); - boolean correctionAvailable = mSuggest.hasMinimalCorrection(); + boolean correctionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasMinimalCorrection(); //|| mCorrectionMode == mSuggest.CORRECTION_FULL; CharSequence typedWord = mWord.getTypedWord(); // If we're in basic correct @@ -1436,7 +1479,7 @@ public class LatinIME extends InputMethodService mHandler.removeMessages(MSG_UPDATE_SUGGESTIONS); updateSuggestions(); } - if (mBestWord != null) { + if (mBestWord != null && mBestWord.length() > 0) { TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord); mJustAccepted = true; pickSuggestion(mBestWord); @@ -1448,6 +1491,12 @@ public class LatinIME extends InputMethodService public void pickSuggestionManually(int index, CharSequence suggestion) { if (mAfterVoiceInput && mShowingVoiceSuggestions) mVoiceInput.logNBestChoose(index); + if (mAfterVoiceInput && !mShowingVoiceSuggestions) { + mVoiceInput.flushAllTextModificationCounters(); + // send this intent AFTER logging any prior aggregated edits. + mVoiceInput.logTextModifiedByChooseSuggestion(suggestion.length()); + } + InputConnection ic = getCurrentInputConnection(); if (ic != null) { ic.beginBatchEdit(); @@ -1480,7 +1529,9 @@ public class LatinIME extends InputMethodService mJustAccepted = true; pickSuggestion(suggestion); // Add the word to the auto dictionary if it's not a known word - checkAddToDictionary(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED); + if (index == 0) { + checkAddToDictionary(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED); + } TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion); // Follow it with a space if (mAutoSpace) { @@ -1526,8 +1577,13 @@ public class LatinIME extends InputMethodService } private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta) { + // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be + // adding words in situations where the user or application really didn't + // want corrections enabled or learned. + if (!(mCorrectionMode == Suggest.CORRECTION_FULL)) return; if (mAutoDictionary.isValidWord(suggestion) - || !mSuggest.isValidWord(suggestion.toString().toLowerCase())) { + || (!mSuggest.isValidWord(suggestion.toString()) + && !mSuggest.isValidWord(suggestion.toString().toLowerCase()))) { mAutoDictionary.addWord(suggestion.toString(), frequencyDelta); } } @@ -1548,6 +1604,11 @@ public class LatinIME extends InputMethodService return false; } + private boolean sameAsTextBeforeCursor(InputConnection ic, CharSequence text) { + CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); + return TextUtils.equals(text, beforeText); + } + public void revertLastWord(boolean deleteChar) { final int length = mComposing.length(); if (!mPredicting && length > 0) { @@ -1679,7 +1740,7 @@ public class LatinIME extends InputMethodService return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext) && !(attribute != null && attribute.privateImeOptions != null && attribute.privateImeOptions.equals(IME_OPTION_NO_MICROPHONE)) - && RecognitionManager.isRecognitionAvailable(this); + && SpeechRecognizer.isRecognitionAvailable(this); } // receive ringer mode changes to detect silent mode diff --git a/java/src/com/android/inputmethod/latin/LatinIMEBackupAgent.java b/java/src/com/android/inputmethod/latin/LatinIMEBackupAgent.java index 62da86cd4..568b31d04 100644 --- a/java/src/com/android/inputmethod/latin/LatinIMEBackupAgent.java +++ b/java/src/com/android/inputmethod/latin/LatinIMEBackupAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. + * Copyright (C) 2008 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 @@ -16,13 +16,13 @@ package com.android.inputmethod.latin; -import android.app.backup.BackupHelperAgent; +import android.app.backup.BackupAgentHelper; import android.app.backup.SharedPreferencesBackupHelper; /** * Backs up the Latin IME shared preferences. */ -public class LatinIMEBackupAgent extends BackupHelperAgent { +public class LatinIMEBackupAgent extends BackupAgentHelper { public void onCreate() { addHelper("shared_pref", new SharedPreferencesBackupHelper(this, diff --git a/java/src/com/android/inputmethod/latin/LatinIMESettings.java b/java/src/com/android/inputmethod/latin/LatinIMESettings.java index f76ec99b6..21b967420 100644 --- a/java/src/com/android/inputmethod/latin/LatinIMESettings.java +++ b/java/src/com/android/inputmethod/latin/LatinIMESettings.java @@ -1,6 +1,6 @@ /* - * Copyright (C) 2008-2009 Google Inc. - * + * Copyright (C) 2008 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 @@ -31,7 +31,7 @@ import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceGroup; import android.preference.Preference.OnPreferenceClickListener; -import android.speech.RecognitionManager; +import android.speech.SpeechRecognizer; import android.text.AutoText; import android.util.Log; @@ -88,7 +88,7 @@ public class LatinIMESettings extends PreferenceActivity .removePreference(mQuickFixes); } if (!LatinIME.VOICE_INSTALLED - || !RecognitionManager.isRecognitionAvailable(this)) { + || !SpeechRecognizer.isRecognitionAvailable(this)) { getPreferenceScreen().removePreference(mVoicePreference); } else { updateVoiceModeSummary(); diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java index 58e1dc767..32cd8a45f 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2008 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 diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java index 2686a93c6..6ba2095c0 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2008 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 @@ -23,6 +23,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.inputmethodservice.Keyboard; import android.inputmethodservice.KeyboardView; +import android.inputmethodservice.KeyboardView.OnKeyboardActionListener; import android.inputmethodservice.Keyboard.Key; import android.os.Handler; import android.os.Message; @@ -43,10 +44,27 @@ public class LatinKeyboardView extends KeyboardView { private Keyboard mPhoneKeyboard; + /** Whether the extension of this keyboard is visible */ private boolean mExtensionVisible; + /** The view that is shown as an extension of this keyboard view */ private LatinKeyboardView mExtension; + /** The popup window that contains the extension of this keyboard */ private PopupWindow mExtensionPopup; + /** Whether this view is an extension of another keyboard */ + private boolean mIsExtensionType; private boolean mFirstEvent; + /** Whether we've started dropping move events because we found a big jump */ + private boolean mDroppingEvents; + /** + * Whether multi-touch disambiguation needs to be disabled for any reason. There are 2 reasons + * for this to happen - (1) if a real multi-touch event has occured and (2) we've opened an + * extension keyboard. + */ + private boolean mDisableDisambiguation; + /** The distance threshold at which we start treating the touch session as a multi-touch */ + private int mJumpThresholdSquare = Integer.MAX_VALUE; + /** The y coordinate of the last row */ + private int mLastRowY; public LatinKeyboardView(Context context, AttributeSet attrs) { super(context, attrs); @@ -61,6 +79,17 @@ public class LatinKeyboardView extends KeyboardView { } @Override + public void setKeyboard(Keyboard k) { + super.setKeyboard(k); + // One-seventh of the keyboard width seems like a reasonable threshold + mJumpThresholdSquare = k.getMinWidth() / 7; + mJumpThresholdSquare *= mJumpThresholdSquare; + // Assuming there are 4 rows, this is the coordinate of the last row + mLastRowY = (k.getHeight() * 3) / 4; + setKeyboardLocal(k); + } + + @Override protected boolean onLongPress(Key key) { if (key.codes[0] == Keyboard.KEYCODE_MODE_CHANGE) { getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS, null); @@ -78,6 +107,83 @@ public class LatinKeyboardView extends KeyboardView { } } + /** + * This function checks to see if we need to handle any sudden jumps in the pointer location + * that could be due to a multi-touch being treated as a move by the firmware or hardware. + * Once a sudden jump is detected, all subsequent move events are discarded + * until an UP is received.<P> + * When a sudden jump is detected, an UP event is simulated at the last position and when + * the sudden moves subside, a DOWN event is simulated for the second key. + * @param me the motion event + * @return true if the event was consumed, so that it doesn't continue to be handled by + * KeyboardView. + */ + private boolean handleSuddenJump(MotionEvent me) { + final int action = me.getAction(); + final int x = (int) me.getX(); + final int y = (int) me.getY(); + boolean result = false; + + // Real multi-touch event? Stop looking for sudden jumps + if (me.getPointerCount() > 1) { + mDisableDisambiguation = true; + } + if (mDisableDisambiguation) { + // If UP, reset the multi-touch flag + if (action == MotionEvent.ACTION_UP) mDisableDisambiguation = false; + return false; + } + + switch (action) { + case MotionEvent.ACTION_DOWN: + // Reset the "session" + mDroppingEvents = false; + mDisableDisambiguation = false; + break; + case MotionEvent.ACTION_MOVE: + // Is this a big jump? + final int distanceSquare = (mLastX - x) * (mLastX - x) + (mLastY - y) * (mLastY - y); + // Check the distance and also if the move is not entirely within the bottom row + // If it's only in the bottom row, it might be an intentional slide gesture + // for language switching + if (distanceSquare > mJumpThresholdSquare + && (mLastY < mLastRowY || y < mLastRowY)) { + // If we're not yet dropping events, start dropping and send an UP event + if (!mDroppingEvents) { + mDroppingEvents = true; + // Send an up event + MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(), + MotionEvent.ACTION_UP, + mLastX, mLastY, me.getMetaState()); + super.onTouchEvent(translated); + translated.recycle(); + } + result = true; + } else if (mDroppingEvents) { + // If moves are small and we're already dropping events, continue dropping + result = true; + } + break; + case MotionEvent.ACTION_UP: + if (mDroppingEvents) { + // Send a down event first, as we dropped a bunch of sudden jumps and assume that + // the user is releasing the touch on the second key. + MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(), + MotionEvent.ACTION_DOWN, + x, y, me.getMetaState()); + super.onTouchEvent(translated); + translated.recycle(); + mDroppingEvents = false; + // Let the up event get processed as well, result = false + } + break; + } + // Track the previous coordinate + mLastX = x; + mLastY = y; + return result; + } + @Override public boolean onTouchEvent(MotionEvent me) { LatinKeyboard keyboard = (LatinKeyboard) getKeyboard(); @@ -86,6 +192,12 @@ public class LatinKeyboardView extends KeyboardView { mLastY = (int) me.getY(); invalidate(); } + // If an extension keyboard is visible or this is an extension keyboard, don't look + // for sudden jumps. Otherwise, if there was a sudden jump, return without processing the + // actual motion event. + if (!mExtensionVisible && !mIsExtensionType + && handleSuddenJump(me)) return true; + // Reset any bounding box controls in the keyboard if (me.getAction() == MotionEvent.ACTION_DOWN) { keyboard.keyReleased(); @@ -139,6 +251,8 @@ public class LatinKeyboardView extends KeyboardView { } else { mFirstEvent = true; } + // Stop processing multi-touch errors + mDisableDisambiguation = true; } return true; } @@ -157,7 +271,15 @@ public class LatinKeyboardView extends KeyboardView { } } + private void setExtensionType(boolean isExtensionType) { + mIsExtensionType = isExtensionType; + } + private boolean openExtension() { + // If the current keyboard is not visible, don't show the popup + if (!isShown()) { + return false; + } if (((LatinKeyboard) getKeyboard()).getExtension() == 0) return false; makePopupWindow(); mExtensionVisible = true; @@ -172,7 +294,9 @@ public class LatinKeyboardView extends KeyboardView { LayoutInflater li = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); mExtension = (LatinKeyboardView) li.inflate(R.layout.input_trans, null); - mExtension.setOnKeyboardActionListener((LatinIME) getContext()); + mExtension.setExtensionType(true); + mExtension.setOnKeyboardActionListener( + new ExtensionKeyboardListener(getOnKeyboardActionListener())); mExtension.setPopupParent(this); mExtension.setPopupOffset(0, -windowLocation[1]); Keyboard keyboard; @@ -181,6 +305,7 @@ public class LatinKeyboardView extends KeyboardView { mExtensionPopup.setContentView(mExtension); mExtensionPopup.setWidth(getWidth()); mExtensionPopup.setHeight(keyboard.getHeight()); + mExtensionPopup.setAnimationStyle(-1); getLocationInWindow(windowLocation); // TODO: Fix the "- 30". mExtension.setPopupOffset(0, -windowLocation[1] - 30); @@ -201,11 +326,42 @@ public class LatinKeyboardView extends KeyboardView { } private void closeExtension() { - mExtension.setVisibility(INVISIBLE); mExtension.closing(); + mExtension.setVisibility(INVISIBLE); mExtensionVisible = false; } + private static class ExtensionKeyboardListener implements OnKeyboardActionListener { + private OnKeyboardActionListener mTarget; + ExtensionKeyboardListener(OnKeyboardActionListener target) { + mTarget = target; + } + public void onKey(int primaryCode, int[] keyCodes) { + mTarget.onKey(primaryCode, keyCodes); + } + public void onPress(int primaryCode) { + mTarget.onPress(primaryCode); + } + public void onRelease(int primaryCode) { + mTarget.onRelease(primaryCode); + } + public void onText(CharSequence text) { + mTarget.onText(text); + } + public void swipeDown() { + // Don't pass through + } + public void swipeLeft() { + // Don't pass through + } + public void swipeRight() { + // Don't pass through + } + public void swipeUp() { + // Don't pass through + } + } + /**************************** INSTRUMENTATION *******************************/ static final boolean DEBUG_AUTO_PLAY = false; @@ -224,9 +380,7 @@ public class LatinKeyboardView extends KeyboardView { private int mLastY; private Paint mPaint; - @Override - public void setKeyboard(Keyboard k) { - super.setKeyboard(k); + private void setKeyboardLocal(Keyboard k) { if (DEBUG_AUTO_PLAY) { findKeys(); if (mHandler2 == null) { diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 712b9cf37..a70bea003 100755 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2008 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 @@ -39,7 +39,7 @@ public class Suggest implements Dictionary.WordCallback { public static final int CORRECTION_BASIC = 1; public static final int CORRECTION_FULL = 2; - private static final int LARGE_DICTIONARY_THRESHOLD = 200 * 1000; + static final int LARGE_DICTIONARY_THRESHOLD = 200 * 1000; private BinaryDictionary mMainDict; @@ -346,11 +346,10 @@ public class Suggest implements Dictionary.WordCallback { if (word == null || word.length() == 0) { return false; } - return (mCorrectionMode == CORRECTION_FULL && mMainDict.isValidWord(word)) - || (mCorrectionMode > CORRECTION_NONE && - ((mUserDictionary != null && mUserDictionary.isValidWord(word))) - || (mAutoDictionary != null && mAutoDictionary.isValidWord(word)) - || (mContactsDictionary != null && mContactsDictionary.isValidWord(word))); + return mMainDict.isValidWord(word) + || (mUserDictionary != null && mUserDictionary.isValidWord(word)) + || (mAutoDictionary != null && mAutoDictionary.isValidWord(word)) + || (mContactsDictionary != null && mContactsDictionary.isValidWord(word)); } private void collectGarbage() { diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java index c5e8ad9a1..d056ceb16 100644 --- a/java/src/com/android/inputmethod/latin/TextEntryState.java +++ b/java/src/com/android/inputmethod/latin/TextEntryState.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2008 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 diff --git a/java/src/com/android/inputmethod/latin/Tutorial.java b/java/src/com/android/inputmethod/latin/Tutorial.java index 03d4858c4..a8123317b 100644 --- a/java/src/com/android/inputmethod/latin/Tutorial.java +++ b/java/src/com/android/inputmethod/latin/Tutorial.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2008 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 diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index e97cb24ba..19f714ae7 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2008 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 @@ -84,11 +84,27 @@ public class WordComposer { */ public void add(int primaryCode, int[] codes) { mTypedWord.append((char) primaryCode); + correctPrimaryJuxtapos(primaryCode, codes); mCodes.add(codes); if (Character.isUpperCase((char) primaryCode)) mCapsCount++; } /** + * Swaps the first and second values in the codes array if the primary code is not the first + * value in the array but the second. This happens when the preferred key is not the key that + * the user released the finger on. + * @param primaryCode the preferred character + * @param codes array of codes based on distance from touch point + */ + private void correctPrimaryJuxtapos(int primaryCode, int[] codes) { + if (codes.length < 2) return; + if (codes[0] > 0 && codes[1] > 0 && codes[0] != primaryCode && codes[1] == primaryCode) { + codes[1] = codes[0]; + codes[0] = primaryCode; + } + } + + /** * Delete the last keystroke as a result of hitting backspace. */ public void deleteLast() { diff --git a/java/src/com/android/inputmethod/voice/VoiceInput.java b/java/src/com/android/inputmethod/voice/VoiceInput.java index e881856dd..ac06ab50d 100644 --- a/java/src/com/android/inputmethod/voice/VoiceInput.java +++ b/java/src/com/android/inputmethod/voice/VoiceInput.java @@ -26,7 +26,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.speech.RecognitionListener; -import android.speech.RecognitionManager; +import android.speech.SpeechRecognizer; import android.speech.RecognizerIntent; import android.util.Log; import android.view.View; @@ -94,6 +94,12 @@ public class VoiceInput implements OnClickListener { public static final int WORKING = 2; public static final int ERROR = 3; + private int mAfterVoiceInputDeleteCount = 0; + private int mAfterVoiceInputInsertCount = 0; + private int mAfterVoiceInputInsertPunctuationCount = 0; + private int mAfterVoiceInputCursorPos = 0; + private int mAfterVoiceInputSelectionSpan = 0; + private int mState = DEFAULT; private final static int MSG_CLOSE_ERROR_DIALOG = 1; @@ -128,7 +134,7 @@ public class VoiceInput implements OnClickListener { public void onCancelVoice(); } - private RecognitionManager mRecognitionManager; + private SpeechRecognizer mSpeechRecognizer; private RecognitionListener mRecognitionListener; private RecognitionView mRecognitionView; private UiListener mUiListener; @@ -141,8 +147,8 @@ public class VoiceInput implements OnClickListener { public VoiceInput(Context context, UiListener uiHandler) { mLogger = VoiceInputLogger.getLogger(context); mRecognitionListener = new ImeRecognitionListener(); - mRecognitionManager = RecognitionManager.createRecognitionManager(context); - mRecognitionManager.setRecognitionListener(mRecognitionListener); + mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(context); + mSpeechRecognizer.setRecognitionListener(mRecognitionListener); mUiListener = uiHandler; mContext = context; newView(); @@ -161,6 +167,87 @@ public class VoiceInput implements OnClickListener { mBlacklist.addApp("com.android.setupwizard"); } + public void setCursorPos(int pos) { + mAfterVoiceInputCursorPos = pos; + } + + public int getCursorPos() { + return mAfterVoiceInputCursorPos; + } + + public void setSelectionSpan(int span) { + mAfterVoiceInputSelectionSpan = span; + } + + public int getSelectionSpan() { + return mAfterVoiceInputSelectionSpan; + } + + public void incrementTextModificationDeleteCount(int count){ + mAfterVoiceInputDeleteCount += count; + // Send up intents for other text modification types + if (mAfterVoiceInputInsertCount > 0) { + logTextModifiedByTypingInsertion(mAfterVoiceInputInsertCount); + mAfterVoiceInputInsertCount = 0; + } + if (mAfterVoiceInputInsertPunctuationCount > 0) { + logTextModifiedByTypingInsertionPunctuation(mAfterVoiceInputInsertPunctuationCount); + mAfterVoiceInputInsertPunctuationCount = 0; + } + + } + + public void incrementTextModificationInsertCount(int count){ + mAfterVoiceInputInsertCount += count; + if (mAfterVoiceInputSelectionSpan > 0) { + // If text was highlighted before inserting the char, count this as + // a delete. + mAfterVoiceInputDeleteCount += mAfterVoiceInputSelectionSpan; + } + // Send up intents for other text modification types + if (mAfterVoiceInputDeleteCount > 0) { + logTextModifiedByTypingDeletion(mAfterVoiceInputDeleteCount); + mAfterVoiceInputDeleteCount = 0; + } + if (mAfterVoiceInputInsertPunctuationCount > 0) { + logTextModifiedByTypingInsertionPunctuation(mAfterVoiceInputInsertPunctuationCount); + mAfterVoiceInputInsertPunctuationCount = 0; + } + } + + public void incrementTextModificationInsertPunctuationCount(int count){ + mAfterVoiceInputInsertPunctuationCount += 1; + if (mAfterVoiceInputSelectionSpan > 0) { + // If text was highlighted before inserting the char, count this as + // a delete. + mAfterVoiceInputDeleteCount += mAfterVoiceInputSelectionSpan; + } + // Send up intents for aggregated non-punctuation insertions + if (mAfterVoiceInputDeleteCount > 0) { + logTextModifiedByTypingDeletion(mAfterVoiceInputDeleteCount); + mAfterVoiceInputDeleteCount = 0; + } + if (mAfterVoiceInputInsertCount > 0) { + logTextModifiedByTypingInsertion(mAfterVoiceInputInsertCount); + mAfterVoiceInputInsertCount = 0; + } + } + + public void flushAllTextModificationCounters() { + if (mAfterVoiceInputInsertCount > 0) { + logTextModifiedByTypingInsertion(mAfterVoiceInputInsertCount); + mAfterVoiceInputInsertCount = 0; + } + if (mAfterVoiceInputDeleteCount > 0) { + logTextModifiedByTypingDeletion(mAfterVoiceInputDeleteCount); + mAfterVoiceInputDeleteCount = 0; + } + if (mAfterVoiceInputInsertPunctuationCount > 0) { + logTextModifiedByTypingInsertionPunctuation(mAfterVoiceInputInsertPunctuationCount); + mAfterVoiceInputInsertPunctuationCount = 0; + } + } + /** * The configuration of the IME changed and may have caused the views to be layed out * again. Restore the state of the recognition view. @@ -247,7 +334,7 @@ public class VoiceInput implements OnClickListener { EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, null /* rely on endpointer default */); - mRecognitionManager.startListening(intent); + mSpeechRecognizer.startListening(intent); } /** @@ -270,7 +357,7 @@ public class VoiceInput implements OnClickListener { } public void destroy() { - mRecognitionManager.destroy(); + mSpeechRecognizer.destroy(); } /** @@ -302,8 +389,20 @@ public class VoiceInput implements OnClickListener { } } - public void logTextModified() { - mLogger.textModified(); + public void logTextModifiedByTypingInsertion(int length) { + mLogger.textModifiedByTypingInsertion(length); + } + + public void logTextModifiedByTypingInsertionPunctuation(int length) { + mLogger.textModifiedByTypingInsertionPunctuation(length); + } + + public void logTextModifiedByTypingDeletion(int length) { + mLogger.textModifiedByTypingDeletion(length); + } + + public void logTextModifiedByChooseSuggestion(int length) { + mLogger.textModifiedByChooseSuggestion(length); } public void logKeyboardWarningDialogShown() { @@ -330,8 +429,8 @@ public class VoiceInput implements OnClickListener { mLogger.punctuationHintDisplayed(); } - public void logVoiceInputDelivered() { - mLogger.voiceInputDelivered(); + public void logVoiceInputDelivered(int length) { + mLogger.voiceInputDelivered(length); } public void logNBestChoose(int index) { @@ -385,7 +484,7 @@ public class VoiceInput implements OnClickListener { // Remove all pending tasks (e.g., timers to cancel voice input) mHandler.removeMessages(MSG_CLOSE_ERROR_DIALOG); - mRecognitionManager.cancel(); + mSpeechRecognizer.cancel(); mUiListener.onCancelVoice(); mRecognitionView.finish(); } @@ -393,20 +492,20 @@ public class VoiceInput implements OnClickListener { private int getErrorStringId(int errorType, boolean endpointed) { switch (errorType) { // We use CLIENT_ERROR to signify that voice search is not available on the device. - case RecognitionManager.ERROR_CLIENT: + case SpeechRecognizer.ERROR_CLIENT: return R.string.voice_not_installed; - case RecognitionManager.ERROR_NETWORK: + case SpeechRecognizer.ERROR_NETWORK: return R.string.voice_network_error; - case RecognitionManager.ERROR_NETWORK_TIMEOUT: + case SpeechRecognizer.ERROR_NETWORK_TIMEOUT: return endpointed ? R.string.voice_network_error : R.string.voice_too_much_speech; - case RecognitionManager.ERROR_AUDIO: + case SpeechRecognizer.ERROR_AUDIO: return R.string.voice_audio_error; - case RecognitionManager.ERROR_SERVER: + case SpeechRecognizer.ERROR_SERVER: return R.string.voice_server_error; - case RecognitionManager.ERROR_SPEECH_TIMEOUT: + case SpeechRecognizer.ERROR_SPEECH_TIMEOUT: return R.string.voice_speech_timeout; - case RecognitionManager.ERROR_NO_MATCH: + case SpeechRecognizer.ERROR_NO_MATCH: return R.string.voice_no_match; default: return R.string.voice_error; } @@ -463,7 +562,7 @@ public class VoiceInput implements OnClickListener { public void onResults(Bundle resultsBundle) { List<String> results = resultsBundle - .getStringArrayList(RecognitionManager.RESULTS_RECOGNITION); + .getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); mState = DEFAULT; final Map<String, List<CharSequence>> alternatives = diff --git a/java/src/com/android/inputmethod/voice/VoiceInputLogger.java b/java/src/com/android/inputmethod/voice/VoiceInputLogger.java index 659033340..9d3a92037 100644 --- a/java/src/com/android/inputmethod/voice/VoiceInputLogger.java +++ b/java/src/com/android/inputmethod/voice/VoiceInputLogger.java @@ -147,12 +147,43 @@ public class VoiceInputLogger { mContext.sendBroadcast(i); } - public void voiceInputDelivered() { - mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.VOICE_INPUT_DELIVERED)); + public void voiceInputDelivered(int length) { + Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.VOICE_INPUT_DELIVERED); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length); + mContext.sendBroadcast(i); + } + + public void textModifiedByTypingInsertion(int length) { + Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE, + LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_TYPING_INSERTION); + mContext.sendBroadcast(i); + } + + public void textModifiedByTypingInsertionPunctuation(int length) { + Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE, + LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_TYPING_INSERTION_PUNCTUATION); + mContext.sendBroadcast(i); + } + + public void textModifiedByTypingDeletion(int length) { + Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE, + LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_TYPING_DELETION); + + mContext.sendBroadcast(i); } - public void textModified() { - mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED)); + public void textModifiedByChooseSuggestion(int length) { + Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE, + LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_CHOOSE_SUGGESTION); + mContext.sendBroadcast(i); } public void nBestChoose(int index) { |