aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/latin/AutoDictionary.java130
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java2
-rwxr-xr-xjava/src/com/android/inputmethod/latin/CandidateView.java2
-rw-r--r--java/src/com/android/inputmethod/latin/CandidateViewContainer.java2
-rw-r--r--java/src/com/android/inputmethod/latin/Dictionary.java2
-rw-r--r--java/src/com/android/inputmethod/latin/InputLanguageSelection.java26
-rw-r--r--java/src/com/android/inputmethod/latin/KeyboardSwitcher.java2
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java85
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIMEBackupAgent.java6
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIMESettings.java8
-rw-r--r--java/src/com/android/inputmethod/latin/LatinKeyboard.java2
-rw-r--r--java/src/com/android/inputmethod/latin/LatinKeyboardView.java166
-rwxr-xr-xjava/src/com/android/inputmethod/latin/Suggest.java13
-rw-r--r--java/src/com/android/inputmethod/latin/TextEntryState.java2
-rw-r--r--java/src/com/android/inputmethod/latin/Tutorial.java2
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java18
-rw-r--r--java/src/com/android/inputmethod/voice/VoiceInput.java137
-rw-r--r--java/src/com/android/inputmethod/voice/VoiceInputLogger.java39
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) {