Remove the "deprecated" classes

bug: 6129704
Change-Id: Ib27f2774444e1f084b19be3fe6f56d25dffa7084
main
Ken Wakasa 2012-03-30 16:08:11 +09:00
parent 22a9a3ecd6
commit 911b8f9d19
60 changed files with 44 additions and 4069 deletions

View File

@ -403,12 +403,6 @@
<attr name="parentStyle" format="string" /> <attr name="parentStyle" format="string" />
</declare-styleable> </declare-styleable>
<!-- TODO: Should be removed. This is no longer required if InputMethodSubtype is supported. -->
<declare-styleable name="KeyboardSet">
<!-- Locale of the keyboard layouts -->
<attr name="keyboardLocale" format="string" />
</declare-styleable>
<declare-styleable name="KeyboardSet_Element"> <declare-styleable name="KeyboardSet_Element">
<!-- This should be aligned with KeyboardId.ELEMENT_* --> <!-- This should be aligned with KeyboardId.ELEMENT_* -->
<attr name="elementName" format="enum"> <attr name="elementName" format="enum">

View File

@ -207,75 +207,6 @@
<!-- Spoken feedback after changing to the shifted phone dialer (symbols) keyboard. --> <!-- Spoken feedback after changing to the shifted phone dialer (symbols) keyboard. -->
<string name="spoken_description_mode_phone_shift">Phone symbols mode</string> <string name="spoken_description_mode_phone_shift">Phone symbols mode</string>
<!-- Voice related labels -->
<!-- Title of the warning dialog that shows when a user initiates voice input for
the first time. -->
<string name="voice_warning_title">Voice input</string>
<!-- Message that gets put at the top of the warning dialog if the user is attempting to use
voice input in a currently unsupported locale. Voice input will work for such a user,
but it will only recognize them in English. -->
<string name="voice_warning_locale_not_supported">Voice input is not currently supported for your language, but does work in English.</string>
<!-- Message of the warning dialog that shows when a user initiates voice input for
the first time, or turns it on in settings. [CHAR LIMIT=200] -->
<string name="voice_warning_may_not_understand">Voice input uses Google\'s speech recognition. <a href="http://m.google.com/privacy">The Mobile Privacy Policy</a> applies.</string>
<!-- An additional part of the warning dialog for voice input that only shows when the user
actually initiates voice input, rather than just turning it on in settings. [CHAR LIMIT=200] -->
<string name="voice_warning_how_to_turn_off">To turn off voice input, go to input method settings.</string>
<!-- Message to show when user enables the voice input settings (which says
"Press the microphone button"). [CHAR LIMIT=100] -->
<string name="voice_hint_dialog_message">To use voice input, press the microphone button.</string>
<!-- Short message to tell the user the system is ready for them to speak. -->
<string name="voice_listening">Speak now</string>
<!-- Short message shown after the user finishes speaking. -->
<string name="voice_working">Working</string>
<!-- Short message shown before the user should speak. -->
<string name="voice_initializing"></string>
<!-- Short message shown when a generic error occurs. -->
<string name="voice_error">Error. Please try again.</string>
<!-- Short message shown for a network error. -->
<string name="voice_network_error">Couldn\'t connect</string>
<!-- Short message shown for a network error where the utterance was really long,
in which case we should suggest that the user speak less. -->
<string name="voice_too_much_speech">Error, too much speech.</string>
<!-- Short message shown for an audio error. -->
<string name="voice_audio_error">Audio problem</string>
<!-- Short message shown for an error with the voice server. -->
<string name="voice_server_error">Server error</string>
<!-- Short message shown when no speech is heard. -->
<string name="voice_speech_timeout">No speech heard</string>
<!-- Short message shown when the server couldn't parse any speech. -->
<string name="voice_no_match">No matches found</string>
<!-- Short message shown when the user initiates voice and voice search is not installed. -->
<string name="voice_not_installed">Voice search not installed</string>
<!-- Short hint shown in candidate view to explain voice input. -->
<string name="voice_swipe_hint"><b>Hint:</b> Swipe across keyboard to speak</string>
<!-- Short hint shown in candidate view to explain that user can speak punctuation. -->
<string name="voice_punctuation_hint"><b>Hint:</b> Next time, try speaking punctuation like \"period\", \"comma\", or \"question mark\".</string>
<!-- Label on button to stop recognition. Must be short to fit on button. -->
<string name="cancel">Cancel</string>
<!-- Label on button when an error occurs -->
<string name="ok">OK</string>
<!-- Preferences item for enabling speech input --> <!-- Preferences item for enabling speech input -->
<string name="voice_input">Voice input key</string> <string name="voice_input">Voice input key</string>
@ -294,9 +225,6 @@
<!-- On settings screen, voice input pop-up menu summary text to never show voice key [CHAR LIMIT=20] --> <!-- On settings screen, voice input pop-up menu summary text to never show voice key [CHAR LIMIT=20] -->
<string name="voice_input_modes_summary_off">Voice input is disabled</string> <string name="voice_input_modes_summary_off">Voice input is disabled</string>
<!-- Title of the dialog for selecting input methods. [CHAR LIMIT=20] -->
<string name="selectInputMethod">Select input method</string>
<!-- Title for configuring input method settings [CHAR LIMIT=35] --> <!-- Title for configuring input method settings [CHAR LIMIT=35] -->
<string name="configure_input_method">Configure input methods</string> <string name="configure_input_method">Configure input methods</string>

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="ar" >
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_arabic" latin:elementKeyboard="@xml/kbd_arabic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="be">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_east_slavic" latin:elementKeyboard="@xml/kbd_east_slavic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="bg">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_bulgarian" latin:elementKeyboard="@xml/kbd_bulgarian"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="cs">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwertz" latin:elementKeyboard="@xml/kbd_qwertz"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="da">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_nordic" latin:elementKeyboard="@xml/kbd_nordic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="de">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwerty" latin:elementKeyboard="@xml/kbd_qwerty"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="de">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwertz" latin:elementKeyboard="@xml/kbd_qwertz"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="el">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_greek" latin:elementKeyboard="@xml/kbd_greek"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="es,es_US">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_spanish" latin:elementKeyboard="@xml/kbd_spanish"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="et">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_nordic" latin:elementKeyboard="@xml/kbd_nordic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="fa" >
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_farsi" latin:elementKeyboard="@xml/kbd_farsi"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="fi">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_nordic" latin:elementKeyboard="@xml/kbd_nordic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="fr_CA">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwerty" latin:elementKeyboard="@xml/kbd_qwerty"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="fr_CH">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwertz" latin:elementKeyboard="@xml/kbd_qwertz"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="fr">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_azerty" latin:elementKeyboard="@xml/kbd_azerty"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="hi">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_hindi" latin:elementKeyboard="@xml/kbd_hindi"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="hr">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwertz" latin:elementKeyboard="@xml/kbd_qwertz"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="hu">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwertz" latin:elementKeyboard="@xml/kbd_qwertz"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="is">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_nordic" latin:elementKeyboard="@xml/kbd_nordic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="iw">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_hebrew" latin:elementKeyboard="@xml/kbd_hebrew"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="ka">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_georgian" latin:elementKeyboard="@xml/kbd_georgian"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="ky">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_east_slavic" latin:elementKeyboard="@xml/kbd_east_slavic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="mk">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_south_slavic" latin:elementKeyboard="@xml/kbd_south_slavic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="nb">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_nordic" latin:elementKeyboard="@xml/kbd_nordic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="pl">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwerty" latin:elementKeyboard="@xml/kbd_qwerty"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="pt">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwerty" latin:elementKeyboard="@xml/kbd_qwerty"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="ro">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwerty" latin:elementKeyboard="@xml/kbd_qwerty"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="ru">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_east_slavic" latin:elementKeyboard="@xml/kbd_east_slavic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="sk">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwerty" latin:elementKeyboard="@xml/kbd_qwerty"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="sl">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwerty" latin:elementKeyboard="@xml/kbd_qwerty"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="sr">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_south_slavic" latin:elementKeyboard="@xml/kbd_south_slavic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="sv">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_nordic" latin:elementKeyboard="@xml/kbd_nordic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="th">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_thai" latin:elementKeyboard="@xml/kbd_thai"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="tr">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwerty" latin:elementKeyboard="@xml/kbd_qwerty"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="uk">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_east_slavic" latin:elementKeyboard="@xml/kbd_east_slavic"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="vi">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwerty" latin:elementKeyboard="@xml/kbd_qwerty"

View File

@ -19,8 +19,7 @@
--> -->
<KeyboardSet <KeyboardSet
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
latin:keyboardLocale="en_GB,en_US">
<Element <Element
latin:elementName="alphabet" latin:elementName="alphabet"
latin:elementKeyboard="@xml/kbd_qwerty" latin:elementKeyboard="@xml/kbd_qwerty"

View File

@ -29,7 +29,6 @@ import android.util.Log;
import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SubtypeSwitcher; import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.SubtypeUtils; import com.android.inputmethod.latin.SubtypeUtils;
@ -68,14 +67,6 @@ public class InputMethodManagerCompatWrapper {
private static final InputMethodManagerCompatWrapper sInstance = private static final InputMethodManagerCompatWrapper sInstance =
new InputMethodManagerCompatWrapper(); new InputMethodManagerCompatWrapper();
public static final boolean SUBTYPE_SUPPORTED;
static {
// This static initializer guarantees that METHOD_getShortcutInputMethodsAndSubtypes is
// already instantiated.
SUBTYPE_SUPPORTED = METHOD_getShortcutInputMethodsAndSubtypes != null;
}
// For the compatibility, IMM will create dummy subtypes if subtypes are not found. // For the compatibility, IMM will create dummy subtypes if subtypes are not found.
// This is required to be false if the current behavior is broken. For now, it's ok to be true. // This is required to be false if the current behavior is broken. For now, it's ok to be true.
public static final boolean FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES = public static final boolean FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES =
@ -87,7 +78,6 @@ public class InputMethodManagerCompatWrapper {
private InputMethodManager mImm; private InputMethodManager mImm;
private PackageManager mPackageManager; private PackageManager mPackageManager;
private ApplicationInfo mApplicationInfo; private ApplicationInfo mApplicationInfo;
private LanguageSwitcherProxy mLanguageSwitcherProxy;
private String mLatinImePackageName; private String mLatinImePackageName;
public static InputMethodManagerCompatWrapper getInstance() { public static InputMethodManagerCompatWrapper getInstance() {
@ -103,39 +93,20 @@ public class InputMethodManagerCompatWrapper {
sInstance.mLatinImePackageName = service.getPackageName(); sInstance.mLatinImePackageName = service.getPackageName();
sInstance.mPackageManager = service.getPackageManager(); sInstance.mPackageManager = service.getPackageManager();
sInstance.mApplicationInfo = service.getApplicationInfo(); sInstance.mApplicationInfo = service.getApplicationInfo();
sInstance.mLanguageSwitcherProxy = LanguageSwitcherProxy.getInstance();
} }
public InputMethodSubtypeCompatWrapper getCurrentInputMethodSubtype() { public InputMethodSubtypeCompatWrapper getCurrentInputMethodSubtype() {
if (!SUBTYPE_SUPPORTED) {
return new InputMethodSubtypeCompatWrapper(
0, 0, mLanguageSwitcherProxy.getInputLocale().toString(), KEYBOARD_MODE, "");
}
Object o = CompatUtils.invoke(mImm, null, METHOD_getCurrentInputMethodSubtype); Object o = CompatUtils.invoke(mImm, null, METHOD_getCurrentInputMethodSubtype);
return new InputMethodSubtypeCompatWrapper(o); return new InputMethodSubtypeCompatWrapper(o);
} }
public InputMethodSubtypeCompatWrapper getLastInputMethodSubtype() { public InputMethodSubtypeCompatWrapper getLastInputMethodSubtype() {
if (!SUBTYPE_SUPPORTED) {
return new InputMethodSubtypeCompatWrapper(
0, 0, mLanguageSwitcherProxy.getInputLocale().toString(), KEYBOARD_MODE, "");
}
Object o = CompatUtils.invoke(mImm, null, METHOD_getLastInputMethodSubtype); Object o = CompatUtils.invoke(mImm, null, METHOD_getLastInputMethodSubtype);
return new InputMethodSubtypeCompatWrapper(o); return new InputMethodSubtypeCompatWrapper(o);
} }
public List<InputMethodSubtypeCompatWrapper> getEnabledInputMethodSubtypeList( public List<InputMethodSubtypeCompatWrapper> getEnabledInputMethodSubtypeList(
InputMethodInfoCompatWrapper imi, boolean allowsImplicitlySelectedSubtypes) { InputMethodInfoCompatWrapper imi, boolean allowsImplicitlySelectedSubtypes) {
if (!SUBTYPE_SUPPORTED) {
String[] languages = mLanguageSwitcherProxy.getEnabledLanguages(
allowsImplicitlySelectedSubtypes);
List<InputMethodSubtypeCompatWrapper> subtypeList =
new ArrayList<InputMethodSubtypeCompatWrapper>();
for (String lang: languages) {
subtypeList.add(new InputMethodSubtypeCompatWrapper(0, 0, lang, KEYBOARD_MODE, ""));
}
return subtypeList;
}
Object retval = CompatUtils.invoke(mImm, null, METHOD_getEnabledInputMethodSubtypeList, Object retval = CompatUtils.invoke(mImm, null, METHOD_getEnabledInputMethodSubtypeList,
(imi != null ? imi.getInputMethodInfo() : null), allowsImplicitlySelectedSubtypes); (imi != null ? imi.getInputMethodInfo() : null), allowsImplicitlySelectedSubtypes);
if (retval == null || !(retval instanceof List<?>) || ((List<?>)retval).isEmpty()) { if (retval == null || !(retval instanceof List<?>) || ((List<?>)retval).isEmpty()) {
@ -228,16 +199,10 @@ public class InputMethodManagerCompatWrapper {
} }
public boolean switchToLastInputMethod(IBinder token) { public boolean switchToLastInputMethod(IBinder token) {
if (SubtypeSwitcher.getInstance().isDummyVoiceMode()) {
return true;
}
return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToLastInputMethod, token); return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToLastInputMethod, token);
} }
public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) { public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
if (SubtypeSwitcher.getInstance().isDummyVoiceMode()) {
return true;
}
return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToNextInputMethod, token, return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToNextInputMethod, token,
onlyCurrentIme); onlyCurrentIme);
} }
@ -253,88 +218,6 @@ public class InputMethodManagerCompatWrapper {
public void showInputMethodPicker() { public void showInputMethodPicker() {
if (mImm == null) return; if (mImm == null) return;
if (SUBTYPE_SUPPORTED) {
mImm.showInputMethodPicker(); mImm.showInputMethodPicker();
return;
}
// The code below are based on {@link InputMethodManager#showInputMethodMenuInternal}.
final InputMethodInfoCompatWrapper myImi = SubtypeUtils.getInputMethodInfo(
mLatinImePackageName);
final List<InputMethodSubtypeCompatWrapper> myImsList = getEnabledInputMethodSubtypeList(
myImi, true);
final InputMethodSubtypeCompatWrapper currentIms = getCurrentInputMethodSubtype();
final List<InputMethodInfoCompatWrapper> imiList = getEnabledInputMethodList();
imiList.remove(myImi);
final PackageManager pm = mPackageManager;
Collections.sort(imiList, new Comparator<InputMethodInfoCompatWrapper>() {
@Override
public int compare(InputMethodInfoCompatWrapper imi1,
InputMethodInfoCompatWrapper imi2) {
final CharSequence imiId1 = imi1.loadLabel(pm) + "/" + imi1.getId();
final CharSequence imiId2 = imi2.loadLabel(pm) + "/" + imi2.getId();
return imiId1.toString().compareTo(imiId2.toString());
}
});
final int myImsCount = myImsList.size();
final int imiCount = imiList.size();
final CharSequence[] items = new CharSequence[myImsCount + imiCount];
int checkedItem = 0;
int index = 0;
final CharSequence myImiLabel = myImi.loadLabel(mPackageManager);
for (int i = 0; i < myImsCount; i++) {
InputMethodSubtypeCompatWrapper ims = myImsList.get(i);
if (currentIms.equals(ims))
checkedItem = index;
final CharSequence title = TextUtils.concat(
ims.getDisplayName(mService, mLatinImePackageName, mApplicationInfo),
" (" + myImiLabel, ")");
items[index] = title;
index++;
}
for (int i = 0; i < imiCount; i++) {
final InputMethodInfoCompatWrapper imi = imiList.get(i);
final CharSequence title = imi.loadLabel(mPackageManager);
items[index] = title;
index++;
}
final InputMethodServiceCompatWrapper service = mService;
final OnClickListener buttonListener = new OnClickListener() {
@Override
public void onClick(DialogInterface di, int whichButton) {
final Intent intent = new Intent("android.settings.INPUT_METHOD_SETTINGS");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
service.startActivity(intent);
}
};
final IBinder token = service.getWindow().getWindow().getAttributes().token;
final OnClickListener selectionListener = new OnClickListener() {
@Override
public void onClick(DialogInterface di, int which) {
di.dismiss();
if (which < myImsCount) {
final int imsIndex = which;
final InputMethodSubtypeCompatWrapper ims = myImsList.get(imsIndex);
service.notifyOnCurrentInputMethodSubtypeChanged(ims);
} else {
final int imiIndex = which - myImsCount;
final InputMethodInfoCompatWrapper imi = imiList.get(imiIndex);
setInputMethodAndSubtype(token, imi.getId(), null);
}
}
};
final AlertDialog.Builder builder = new AlertDialog.Builder(mService)
.setTitle(mService.getString(R.string.selectInputMethod))
.setNeutralButton(R.string.configure_input_method, buttonListener)
.setSingleChoiceItems(items, checkedItem, selectionListener);
mService.showOptionDialogInternal(builder.create());
} }
} }

View File

@ -23,7 +23,6 @@ import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.latin.SubtypeSwitcher; import com.android.inputmethod.latin.SubtypeSwitcher;
@ -87,9 +86,6 @@ public class InputMethodServiceCompatWrapper extends InputMethodService {
if (subtype != null) { if (subtype != null) {
if (!InputMethodManagerCompatWrapper.FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES if (!InputMethodManagerCompatWrapper.FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES
&& !subtype.isDummy()) return; && !subtype.isDummy()) return;
if (!InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) {
LanguageSwitcherProxy.getInstance().setLocale(subtype.getLocale());
}
SubtypeSwitcher.getInstance().updateSubtype(subtype); SubtypeSwitcher.getInstance().updateSubtype(subtype);
} }
} }

View File

@ -1,90 +0,0 @@
/*
* Copyright (C) 2011 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.deprecated.languageswitcher.LanguageSwitcher;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.Settings;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import java.util.Locale;
// This class is used only when the IME doesn't use method.xml for language switching.
public class LanguageSwitcherProxy implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final LanguageSwitcherProxy sInstance = new LanguageSwitcherProxy();
private LatinIME mService;
private LanguageSwitcher mLanguageSwitcher;
private SharedPreferences mPrefs;
public static LanguageSwitcherProxy getInstance() {
if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return null;
return sInstance;
}
public static void init(LatinIME service, SharedPreferences prefs) {
if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return;
final Configuration conf = service.getResources().getConfiguration();
sInstance.mLanguageSwitcher = new LanguageSwitcher(service);
sInstance.mLanguageSwitcher.loadLocales(prefs, conf.locale);
sInstance.mPrefs = prefs;
sInstance.mService = service;
prefs.registerOnSharedPreferenceChangeListener(sInstance);
}
public static void onConfigurationChanged(Configuration conf) {
if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return;
sInstance.mLanguageSwitcher.onConfigurationChanged(conf, sInstance.mPrefs);
}
public static void loadSettings() {
if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return;
sInstance.mLanguageSwitcher.loadLocales(sInstance.mPrefs, null);
}
public int getLocaleCount() {
return mLanguageSwitcher.getLocaleCount();
}
public String[] getEnabledLanguages(boolean allowImplicitlySelectedLanguages) {
return mLanguageSwitcher.getEnabledLanguages(allowImplicitlySelectedLanguages);
}
public Locale getInputLocale() {
return mLanguageSwitcher.getInputLocale();
}
public void setLocale(String localeStr) {
mLanguageSwitcher.setLocale(localeStr);
mLanguageSwitcher.persist(mPrefs);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// PREF_SELECTED_LANGUAGES: enabled input subtypes
// PREF_INPUT_LANGUAGE: current input subtype
if (key.equals(Settings.PREF_SELECTED_LANGUAGES)
|| key.equals(Settings.PREF_INPUT_LANGUAGE)) {
mLanguageSwitcher.loadLocales(prefs, null);
if (mService != null) {
mService.onRefreshKeyboard();
}
}
}
}

View File

@ -1,854 +0,0 @@
/*
* Copyright (C) 2010 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.provider.Browser;
import android.speech.SpeechRecognizer;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.URLSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.widget.TextView;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodServiceCompatWrapper;
import com.android.inputmethod.compat.SharedPreferencesCompat;
import com.android.inputmethod.deprecated.voice.FieldContext;
import com.android.inputmethod.deprecated.voice.Hints;
import com.android.inputmethod.deprecated.voice.SettingsUtil;
import com.android.inputmethod.deprecated.voice.VoiceInput;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.LatinKeyboardView;
import com.android.inputmethod.latin.EditingUtils;
import com.android.inputmethod.latin.LastComposedWord;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinIME.UIHandler;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StringUtils;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.Utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class VoiceProxy implements VoiceInput.UiListener {
private static final VoiceProxy sInstance = new VoiceProxy();
public static final boolean VOICE_INSTALLED =
!InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED;
private static final boolean ENABLE_VOICE_BUTTON = true;
private static final String PREF_VOICE_MODE = "voice_mode";
// Whether or not the user has used voice input before (and thus, whether to show the
// first-run warning dialog or not).
private static final String PREF_HAS_USED_VOICE_INPUT = "has_used_voice_input";
// Whether or not the user has used voice input from an unsupported locale UI before.
// For example, the user has a Chinese UI but activates voice input.
private static final String PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE =
"has_used_voice_input_unsupported_locale";
private static final int RECOGNITIONVIEW_HEIGHT_THRESHOLD_RATIO = 6;
// TODO: Adjusted on phones for now
private static final int RECOGNITIONVIEW_MINIMUM_HEIGHT_DIP = 244;
private static final String TAG = VoiceProxy.class.getSimpleName();
private static final boolean DEBUG = LatinImeLogger.sDBG;
private boolean mAfterVoiceInput;
private boolean mConfigurationChanging;
private boolean mHasUsedVoiceInput;
private boolean mHasUsedVoiceInputUnsupportedLocale;
private boolean mImmediatelyAfterVoiceInput;
private boolean mIsShowingHint;
private boolean mLocaleSupportedForVoiceInput;
private boolean mPasswordText;
private boolean mRecognizing;
private boolean mShowingVoiceSuggestions;
private boolean mVoiceButtonEnabled;
private boolean mVoiceButtonOnPrimary;
private boolean mVoiceInputHighlighted;
private int mMinimumVoiceRecognitionViewHeightPixel;
private InputMethodManagerCompatWrapper mImm;
private LatinIME mService;
private AlertDialog mVoiceWarningDialog;
private VoiceInput mVoiceInput;
private final VoiceResults mVoiceResults = new VoiceResults();
private Hints mHints;
private UIHandler mHandler;
private SubtypeSwitcher mSubtypeSwitcher;
// For each word, a list of potential replacements, usually from voice.
private final Map<String, List<CharSequence>> mWordToSuggestions =
new HashMap<String, List<CharSequence>>();
public static VoiceProxy init(LatinIME context, SharedPreferences prefs, UIHandler h) {
sInstance.initInternal(context, prefs, h);
return sInstance;
}
public static VoiceProxy getInstance() {
return sInstance;
}
private void initInternal(LatinIME service, SharedPreferences prefs, UIHandler h) {
if (!VOICE_INSTALLED) {
return;
}
mService = service;
mHandler = h;
mMinimumVoiceRecognitionViewHeightPixel = Utils.dipToPixel(
Utils.getDipScale(service), RECOGNITIONVIEW_MINIMUM_HEIGHT_DIP);
mImm = InputMethodManagerCompatWrapper.getInstance();
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
mVoiceInput = new VoiceInput(service, this);
mHints = new Hints(service, prefs, new Hints.Display() {
@Override
public void showHint(int viewResource) {
View view = LayoutInflater.from(mService).inflate(viewResource, null);
mIsShowingHint = true;
}
});
}
private VoiceProxy() {
// Intentional empty constructor for singleton.
}
public void resetVoiceStates(boolean isPasswordText) {
mAfterVoiceInput = false;
mImmediatelyAfterVoiceInput = false;
mShowingVoiceSuggestions = false;
mVoiceInputHighlighted = false;
mPasswordText = isPasswordText;
}
public void flushVoiceInputLogs() {
if (!VOICE_INSTALLED) {
return;
}
if (!mConfigurationChanging) {
if (mAfterVoiceInput) {
mVoiceInput.flushAllTextModificationCounters();
mVoiceInput.logInputEnded();
}
mVoiceInput.flushLogs();
mVoiceInput.cancel();
}
}
public void flushAndLogAllTextModificationCounters(int index, CharSequence suggestion,
String wordSeparators) {
if (!VOICE_INSTALLED) {
return;
}
if (mAfterVoiceInput && mShowingVoiceSuggestions) {
mVoiceInput.flushAllTextModificationCounters();
// send this intent AFTER logging any prior aggregated edits.
mVoiceInput.logTextModifiedByChooseSuggestion(suggestion.toString(), index,
wordSeparators, mService.getCurrentInputConnection());
}
}
private void showVoiceWarningDialog(final boolean swipe, IBinder token) {
if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
return;
}
AlertDialog.Builder builder = new UrlLinkAlertDialogBuilder(mService);
builder.setCancelable(true);
builder.setIcon(R.drawable.ic_mic_dialog);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
mVoiceInput.logKeyboardWarningDialogOk();
reallyStartListening(swipe);
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
mVoiceInput.logKeyboardWarningDialogCancel();
switchToLastInputMethod();
}
});
// When the dialog is dismissed by user's cancellation, switch back to the last input method
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface arg0) {
mVoiceInput.logKeyboardWarningDialogCancel();
switchToLastInputMethod();
}
});
final CharSequence message;
if (mLocaleSupportedForVoiceInput) {
message = TextUtils.concat(
mService.getText(R.string.voice_warning_may_not_understand), "\n\n",
mService.getText(R.string.voice_warning_how_to_turn_off));
} else {
message = TextUtils.concat(
mService.getText(R.string.voice_warning_locale_not_supported), "\n\n",
mService.getText(R.string.voice_warning_may_not_understand), "\n\n",
mService.getText(R.string.voice_warning_how_to_turn_off));
}
builder.setMessage(message);
builder.setTitle(R.string.voice_warning_title);
mVoiceWarningDialog = builder.create();
final Window window = mVoiceWarningDialog.getWindow();
final WindowManager.LayoutParams lp = window.getAttributes();
lp.token = token;
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
window.setAttributes(lp);
window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
mVoiceInput.logKeyboardWarningDialogShown();
mVoiceWarningDialog.show();
}
private static class UrlLinkAlertDialogBuilder extends AlertDialog.Builder {
private AlertDialog mAlertDialog;
public UrlLinkAlertDialogBuilder(Context context) {
super(context);
}
@Override
public AlertDialog.Builder setMessage(CharSequence message) {
return super.setMessage(replaceURLSpan(message));
}
private Spanned replaceURLSpan(CharSequence message) {
// Replace all spans with the custom span
final SpannableStringBuilder ssb = new SpannableStringBuilder(message);
for (URLSpan span : ssb.getSpans(0, ssb.length(), URLSpan.class)) {
int spanStart = ssb.getSpanStart(span);
int spanEnd = ssb.getSpanEnd(span);
int spanFlags = ssb.getSpanFlags(span);
ssb.removeSpan(span);
ssb.setSpan(new ClickableSpan(span.getURL()), spanStart, spanEnd, spanFlags);
}
return ssb;
}
@Override
public AlertDialog create() {
final AlertDialog dialog = super.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
// Make URL in the dialog message click-able.
TextView textView = (TextView) mAlertDialog.findViewById(android.R.id.message);
if (textView != null) {
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
}
});
mAlertDialog = dialog;
return dialog;
}
class ClickableSpan extends URLSpan {
public ClickableSpan(String url) {
super(url);
}
@Override
public void onClick(View widget) {
Uri uri = Uri.parse(getURL());
Context context = widget.getContext();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
// Add this flag to start an activity from service
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
// Dismiss the warning dialog and go back to the previous IME.
// TODO: If we can find a way to bring the new activity to front while keeping
// the warning dialog, we don't need to dismiss it here.
mAlertDialog.cancel();
context.startActivity(intent);
}
}
}
public void showPunctuationHintIfNecessary() {
if (!VOICE_INSTALLED) {
return;
}
InputConnection ic = mService.getCurrentInputConnection();
if (!mImmediatelyAfterVoiceInput && mAfterVoiceInput && ic != null) {
if (mHints.showPunctuationHintIfNecessary(ic)) {
mVoiceInput.logPunctuationHintDisplayed();
}
}
mImmediatelyAfterVoiceInput = false;
}
public void hideVoiceWindow() {
if (!VOICE_INSTALLED) {
return;
}
if (!mConfigurationChanging) {
if (mAfterVoiceInput)
mVoiceInput.logInputEnded();
if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
mVoiceInput.logKeyboardWarningDialogDismissed();
mVoiceWarningDialog.dismiss();
mVoiceWarningDialog = null;
}
if (VOICE_INSTALLED & mRecognizing) {
mVoiceInput.cancel();
}
}
mWordToSuggestions.clear();
}
public void setCursorAndSelection(int newSelEnd, int newSelStart) {
if (!VOICE_INSTALLED) {
return;
}
if (mAfterVoiceInput) {
mVoiceInput.setCursorPos(newSelEnd);
mVoiceInput.setSelectionSpan(newSelEnd - newSelStart);
}
}
public void setVoiceInputHighlighted(boolean b) {
mVoiceInputHighlighted = b;
}
public void setShowingVoiceSuggestions(boolean b) {
mShowingVoiceSuggestions = b;
}
public boolean isVoiceButtonEnabled() {
return mVoiceButtonEnabled;
}
public boolean isVoiceButtonOnPrimary() {
return mVoiceButtonOnPrimary;
}
public boolean isVoiceInputHighlighted() {
return mVoiceInputHighlighted;
}
public boolean isRecognizing() {
return mRecognizing;
}
public boolean needsToShowWarningDialog() {
return !mHasUsedVoiceInput
|| (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale);
}
public boolean getAndResetIsShowingHint() {
boolean ret = mIsShowingHint;
mIsShowingHint = false;
return ret;
}
private void revertVoiceInput() {
InputConnection ic = mService.getCurrentInputConnection();
if (ic != null) ic.commitText("", 1);
mService.updateSuggestions();
mVoiceInputHighlighted = false;
}
public void commitVoiceInput() {
if (VOICE_INSTALLED && mVoiceInputHighlighted) {
InputConnection ic = mService.getCurrentInputConnection();
if (ic != null) ic.finishComposingText();
mService.updateSuggestions();
mVoiceInputHighlighted = false;
}
}
public boolean logAndRevertVoiceInput() {
if (!VOICE_INSTALLED) {
return false;
}
if (mVoiceInputHighlighted) {
mVoiceInput.incrementTextModificationDeleteCount(
mVoiceResults.candidates.get(0).toString().length());
revertVoiceInput();
return true;
} else {
return false;
}
}
public void rememberReplacedWord(CharSequence suggestion,String wordSeparators) {
if (!VOICE_INSTALLED) {
return;
}
if (mShowingVoiceSuggestions) {
// Retain the replaced word in the alternatives array.
String wordToBeReplaced = EditingUtils.getWordAtCursor(
mService.getCurrentInputConnection(), wordSeparators);
if (!mWordToSuggestions.containsKey(wordToBeReplaced)) {
wordToBeReplaced = wordToBeReplaced.toLowerCase();
}
if (mWordToSuggestions.containsKey(wordToBeReplaced)) {
List<CharSequence> suggestions = mWordToSuggestions.get(wordToBeReplaced);
if (suggestions.contains(suggestion)) {
suggestions.remove(suggestion);
}
suggestions.add(wordToBeReplaced);
mWordToSuggestions.remove(wordToBeReplaced);
mWordToSuggestions.put(suggestion.toString(), suggestions);
}
}
}
public void handleBackspace() {
if (!VOICE_INSTALLED) {
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);
}
}
}
public void handleCharacter() {
if (!VOICE_INSTALLED) {
return;
}
commitVoiceInput();
if (mAfterVoiceInput) {
// Assume input length is 1. This assumption fails for smiley face insertions.
mVoiceInput.incrementTextModificationInsertCount(1);
}
}
public void handleSeparator() {
if (!VOICE_INSTALLED) {
return;
}
commitVoiceInput();
if (mAfterVoiceInput){
// Assume input length is 1. This assumption fails for smiley face insertions.
mVoiceInput.incrementTextModificationInsertPunctuationCount(1);
}
}
public void handleClose() {
if (!VOICE_INSTALLED) {
return;
}
if (mRecognizing) {
mVoiceInput.cancel();
}
}
public void handleVoiceResults(boolean capitalizeFirstWord) {
if (!VOICE_INSTALLED) {
return;
}
mAfterVoiceInput = true;
mImmediatelyAfterVoiceInput = true;
InputConnection ic = mService.getCurrentInputConnection();
if (!mService.isFullscreenMode()) {
// Start listening for updates to the text from typing, etc.
if (ic != null) {
ExtractedTextRequest req = new ExtractedTextRequest();
ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR);
}
}
mService.vibrate();
final List<CharSequence> nBest = new ArrayList<CharSequence>();
for (String c : mVoiceResults.candidates) {
if (capitalizeFirstWord) {
c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length());
}
nBest.add(c);
}
if (nBest.size() == 0) {
return;
}
String bestResult = nBest.get(0).toString();
mVoiceInput.logVoiceInputDelivered(bestResult.length());
mHints.registerVoiceResult(bestResult);
if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text
mService.commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR);
EditingUtils.appendText(ic, bestResult);
if (ic != null) ic.endBatchEdit();
mVoiceInputHighlighted = true;
mWordToSuggestions.putAll(mVoiceResults.alternatives);
onCancelVoice();
}
public void switchToRecognitionStatusView(final Configuration configuration) {
if (!VOICE_INSTALLED) {
return;
}
mHandler.post(new Runnable() {
@Override
public void run() {
// mService.setCandidatesViewShown(false);
mRecognizing = true;
mVoiceInput.newView();
View v = mVoiceInput.getView();
ViewParent p = v.getParent();
if (p != null && p instanceof ViewGroup) {
((ViewGroup) p).removeView(v);
}
View keyboardView = KeyboardSwitcher.getInstance().getKeyboardView();
// The full height of the keyboard is difficult to calculate
// as the dimension is expressed in "mm" and not in "pixel"
// As we add mm, we don't know how the rounding is going to work
// thus we may end up with few pixels extra (or less).
if (keyboardView != null) {
View popupLayout = v.findViewById(R.id.popup_layout);
final int displayHeight =
mService.getResources().getDisplayMetrics().heightPixels;
final int currentHeight = popupLayout.getLayoutParams().height;
final int keyboardHeight = keyboardView.getHeight();
if (mMinimumVoiceRecognitionViewHeightPixel > keyboardHeight
|| mMinimumVoiceRecognitionViewHeightPixel > currentHeight) {
popupLayout.getLayoutParams().height =
mMinimumVoiceRecognitionViewHeightPixel;
} else if (keyboardHeight > currentHeight || keyboardHeight
> (displayHeight / RECOGNITIONVIEW_HEIGHT_THRESHOLD_RATIO)) {
popupLayout.getLayoutParams().height = keyboardHeight;
}
}
mService.setInputView(v);
mService.updateInputViewShown();
if (configuration != null) {
mVoiceInput.onConfigurationChanged(configuration);
}
}});
}
private void switchToLastInputMethod() {
if (!VOICE_INSTALLED) {
return;
}
final IBinder token = mService.getWindow().getWindow().getAttributes().token;
new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
return mImm.switchToLastInputMethod(token);
}
@Override
protected void onPostExecute(Boolean result) {
// Calls in this method need to be done in the same thread as the thread which
// called switchToLastInputMethod()
if (!result) {
if (DEBUG) {
Log.d(TAG, "Couldn't switch back to last IME.");
}
// Because the current IME and subtype failed to switch to any other IME and
// subtype by switchToLastInputMethod, the current IME and subtype should keep
// being LatinIME and voice subtype in the next time. And for re-showing voice
// mode, the state of voice input should be reset and the voice view should be
// hidden.
mVoiceInput.reset();
mService.requestHideSelf(0);
} else {
// Notify an event that the current subtype was changed. This event will be
// handled if "onCurrentInputMethodSubtypeChanged" can't be implemented
// when the API level is 10 or previous.
mService.notifyOnCurrentInputMethodSubtypeChanged(null);
}
}
}.execute();
}
private void reallyStartListening(boolean swipe) {
if (!VOICE_INSTALLED) {
return;
}
if (!mHasUsedVoiceInput) {
// The user has started a voice input, so remember that in the
// future (so we don't show the warning dialog after the first run).
SharedPreferences.Editor editor =
PreferenceManager.getDefaultSharedPreferences(mService).edit();
editor.putBoolean(PREF_HAS_USED_VOICE_INPUT, true);
SharedPreferencesCompat.apply(editor);
mHasUsedVoiceInput = true;
}
if (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale) {
// The user has started a voice input from an unsupported locale, so remember that
// in the future (so we don't show the warning dialog the next time they do this).
SharedPreferences.Editor editor =
PreferenceManager.getDefaultSharedPreferences(mService).edit();
editor.putBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, true);
SharedPreferencesCompat.apply(editor);
mHasUsedVoiceInputUnsupportedLocale = true;
}
// Clear N-best suggestions
mService.clearSuggestions();
FieldContext context = makeFieldContext();
mVoiceInput.startListening(context, swipe);
switchToRecognitionStatusView(null);
}
public void startListening(final boolean swipe, IBinder token) {
if (!VOICE_INSTALLED) {
return;
}
// TODO: remove swipe which is no longer used.
if (needsToShowWarningDialog()) {
// Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel.
showVoiceWarningDialog(swipe, token);
} else {
reallyStartListening(swipe);
}
}
private boolean fieldCanDoVoice(FieldContext fieldContext) {
return !mPasswordText
&& mVoiceInput != null
&& !mVoiceInput.isBlacklistedField(fieldContext);
}
private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo editorInfo) {
@SuppressWarnings("deprecation")
final boolean noMic = StringUtils.inPrivateImeOptions(null,
LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)
|| StringUtils.inPrivateImeOptions(mService.getPackageName(),
LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo);
return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext) && !noMic
&& SpeechRecognizer.isRecognitionAvailable(mService);
}
public static boolean isRecognitionAvailable(Context context) {
return SpeechRecognizer.isRecognitionAvailable(context);
}
public void loadSettings(EditorInfo editorInfo, SharedPreferences sp) {
if (!VOICE_INSTALLED) {
return;
}
mHasUsedVoiceInput = sp.getBoolean(PREF_HAS_USED_VOICE_INPUT, false);
mHasUsedVoiceInputUnsupportedLocale =
sp.getBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, false);
mLocaleSupportedForVoiceInput = SubtypeSwitcher.isVoiceSupported(
mService, SubtypeSwitcher.getInstance().getInputLocaleStr());
final String voiceMode = sp.getString(PREF_VOICE_MODE,
mService.getString(R.string.voice_mode_main));
mVoiceButtonEnabled = !voiceMode.equals(mService.getString(R.string.voice_mode_off))
&& shouldShowVoiceButton(makeFieldContext(), editorInfo);
mVoiceButtonOnPrimary = voiceMode.equals(mService.getString(R.string.voice_mode_main));
}
public void destroy() {
if (!VOICE_INSTALLED) {
return;
}
if (mVoiceInput != null) {
mVoiceInput.destroy();
}
}
public void onStartInputView(IBinder keyboardViewToken) {
if (!VOICE_INSTALLED) {
return;
}
// If keyboardViewToken is null, keyboardView is not attached but voiceView is attached.
IBinder windowToken = keyboardViewToken != null ? keyboardViewToken
: mVoiceInput.getView().getWindowToken();
// If IME is in voice mode, but still needs to show the voice warning dialog,
// keep showing the warning.
if (mSubtypeSwitcher.isVoiceMode() && windowToken != null) {
// Close keyboard view if it is been shown.
final LatinKeyboardView keyboardView = KeyboardSwitcher.getInstance().getKeyboardView();
if (keyboardView != null && keyboardView.isShown())
keyboardView.purgeKeyboardAndClosing();
startListening(false, windowToken);
}
// If we have no token, onAttachedToWindow will take care of showing dialog and start
// listening.
}
public void onAttachedToWindow() {
if (!VOICE_INSTALLED) {
return;
}
// After onAttachedToWindow, we can show the voice warning dialog. See startListening()
// above.
VoiceInputWrapper.getInstance().setVoiceInput(mVoiceInput, mSubtypeSwitcher);
}
public void onConfigurationChanged(Configuration configuration) {
if (!VOICE_INSTALLED) {
return;
}
if (mRecognizing) {
switchToRecognitionStatusView(configuration);
}
}
@Override
public void onCancelVoice() {
if (!VOICE_INSTALLED) {
return;
}
if (mRecognizing) {
if (mSubtypeSwitcher.isVoiceMode()) {
// If voice mode is being canceled within LatinIME (i.e. time-out or user
// cancellation etc.), onCancelVoice() will be called first. LatinIME thinks it's
// still in voice mode. LatinIME needs to call switchToLastInputMethod().
// Note that onCancelVoice() will be called again from SubtypeSwitcher.
switchToLastInputMethod();
} else if (mSubtypeSwitcher.isKeyboardMode()) {
// If voice mode is being canceled out of LatinIME (i.e. by user's IME switching or
// as a result of switchToLastInputMethod() etc.),
// onCurrentInputMethodSubtypeChanged() will be called first. LatinIME will know
// that it's in keyboard mode and SubtypeSwitcher will call onCancelVoice().
mRecognizing = false;
mService.switchToKeyboardView();
}
}
}
@Override
public void onVoiceResults(List<String> candidates,
Map<String, List<CharSequence>> alternatives) {
if (!VOICE_INSTALLED) {
return;
}
if (!mRecognizing) {
return;
}
mVoiceResults.candidates = candidates;
mVoiceResults.alternatives = alternatives;
mHandler.updateVoiceResults();
}
private FieldContext makeFieldContext() {
SubtypeSwitcher switcher = SubtypeSwitcher.getInstance();
return new FieldContext(mService.getCurrentInputConnection(),
mService.getCurrentInputEditorInfo(), switcher.getInputLocaleStr(),
switcher.getEnabledLanguages());
}
// TODO: make this private (proguard issue)
public static class VoiceResults {
List<String> candidates;
Map<String, List<CharSequence>> alternatives;
}
public static class VoiceInputWrapper {
private static final VoiceInputWrapper sInputWrapperInstance = new VoiceInputWrapper();
private VoiceInput mVoiceInput;
public static VoiceInputWrapper getInstance() {
return sInputWrapperInstance;
}
private void setVoiceInput(VoiceInput voiceInput, SubtypeSwitcher switcher) {
if (!VOICE_INSTALLED) {
return;
}
if (mVoiceInput == null && voiceInput != null) {
mVoiceInput = voiceInput;
}
switcher.setVoiceInputWrapper(this);
}
private VoiceInputWrapper() {
}
public void cancel() {
if (!VOICE_INSTALLED) {
return;
}
if (mVoiceInput != null) mVoiceInput.cancel();
}
public void reset() {
if (!VOICE_INSTALLED) {
return;
}
if (mVoiceInput != null) mVoiceInput.reset();
}
}
// A list of locales which are supported by default for voice input, unless we get a
// different list from Gservices.
private static final String DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES =
"en " +
"en_US " +
"en_GB " +
"en_AU " +
"en_CA " +
"en_IE " +
"en_IN " +
"en_NZ " +
"en_SG " +
"en_ZA ";
public static String getSupportedLocalesString (ContentResolver resolver) {
return SettingsUtil.getSettingsString(
resolver,
SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
}
public void startChangingConfiguration() {
mConfigurationChanging = true;
}
public void finishChangingConfiguration() {
mConfigurationChanging = false;
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (C) 2011 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.deprecated.compat;
import com.android.common.userhappiness.UserHappinessSignals;
import com.android.inputmethod.compat.CompatUtils;
import java.lang.reflect.Method;
public class VoiceInputLoggerCompatUtils {
public static final String EXTRA_TEXT_REPLACED_LENGTH = "length";
public static final String EXTRA_BEFORE_N_BEST_CHOOSE = "before";
public static final String EXTRA_AFTER_N_BEST_CHOOSE = "after";
private static final Method METHOD_UserHappinessSignals_setHasVoiceLoggingInfo =
CompatUtils.getMethod(UserHappinessSignals.class, "setHasVoiceLoggingInfo",
boolean.class);
public static void setHasVoiceLoggingInfoCompat(boolean hasLoggingInfo) {
CompatUtils.invoke(null, null, METHOD_UserHappinessSignals_setHasVoiceLoggingInfo,
hasLoggingInfo);
}
}

View File

@ -1,255 +0,0 @@
/*
* Copyright (C) 2008-2009 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.languageswitcher;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Pair;
import com.android.inputmethod.compat.SharedPreferencesCompat;
import com.android.inputmethod.keyboard.KeyboardSet;
import com.android.inputmethod.latin.DictionaryFactory;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.Settings;
import com.android.inputmethod.latin.StringUtils;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map.Entry;
import java.util.TreeMap;
public class InputLanguageSelection extends PreferenceActivity {
private SharedPreferences mPrefs;
private String mSelectedLanguages;
private HashMap<CheckBoxPreference, Locale> mLocaleMap =
new HashMap<CheckBoxPreference, Locale>();
private static class LocaleEntry implements Comparable<Object> {
private static Collator sCollator = Collator.getInstance();
private String mLabel;
public final Locale mLocale;
public LocaleEntry(String label, Locale locale) {
this.mLabel = label;
this.mLocale = locale;
}
@Override
public String toString() {
return this.mLabel;
}
@Override
public int compareTo(Object o) {
return sCollator.compare(this.mLabel, ((LocaleEntry) o).mLabel);
}
}
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.language_prefs);
// Get the settings preferences
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
mSelectedLanguages = mPrefs.getString(Settings.PREF_SELECTED_LANGUAGES, "");
String[] languageList = mSelectedLanguages.split(",");
ArrayList<LocaleEntry> availableLanguages = getUniqueLocales();
PreferenceGroup parent = getPreferenceScreen();
final HashMap<Long, LocaleEntry> dictionaryIdLocaleMap = new HashMap<Long, LocaleEntry>();
final TreeMap<LocaleEntry, Boolean> localeHasDictionaryMap =
new TreeMap<LocaleEntry, Boolean>();
for (int i = 0; i < availableLanguages.size(); i++) {
LocaleEntry loc = availableLanguages.get(i);
Locale locale = loc.mLocale;
final Pair<Long, Boolean> hasDictionaryOrLayout = hasDictionaryOrLayout(locale);
final Long dictionaryId = hasDictionaryOrLayout.first;
final boolean hasLayout = hasDictionaryOrLayout.second;
final boolean hasDictionary = dictionaryId != null;
// Add this locale to the supported list if:
// 1) this locale has a layout/ 2) this locale has a dictionary
// If some locales have no layout but have a same dictionary, the shortest locale
// will be added to the supported list.
if (!hasLayout && !hasDictionary) {
continue;
}
if (hasLayout) {
localeHasDictionaryMap.put(loc, hasDictionary);
}
if (!hasDictionary) {
continue;
}
if (dictionaryIdLocaleMap.containsKey(dictionaryId)) {
final String newLocale = locale.toString();
final String oldLocale =
dictionaryIdLocaleMap.get(dictionaryId).mLocale.toString();
// Check if this locale is more appropriate to be the candidate of the input locale.
if (oldLocale.length() <= newLocale.length() && !hasLayout) {
// Don't add this new locale to the map<dictionary id, locale> if:
// 1) the new locale's name is longer than the existing one, and
// 2) the new locale doesn't have its layout
continue;
}
}
dictionaryIdLocaleMap.put(dictionaryId, loc);
}
for (LocaleEntry localeEntry : dictionaryIdLocaleMap.values()) {
if (!localeHasDictionaryMap.containsKey(localeEntry)) {
localeHasDictionaryMap.put(localeEntry, true);
}
}
for (Entry<LocaleEntry, Boolean> entry : localeHasDictionaryMap.entrySet()) {
final LocaleEntry localeEntry = entry.getKey();
final Locale locale = localeEntry.mLocale;
final Boolean hasDictionary = entry.getValue();
CheckBoxPreference pref = new CheckBoxPreference(this);
pref.setTitle(localeEntry.mLabel);
boolean checked = isLocaleIn(locale, languageList);
pref.setChecked(checked);
if (hasDictionary) {
pref.setSummary(R.string.has_dictionary);
}
mLocaleMap.put(pref, locale);
parent.addPreference(pref);
}
}
private boolean isLocaleIn(Locale locale, String[] list) {
String lang = get5Code(locale);
for (int i = 0; i < list.length; i++) {
if (lang.equalsIgnoreCase(list[i])) return true;
}
return false;
}
private Pair<Long, Boolean> hasDictionaryOrLayout(Locale locale) {
if (locale == null) return new Pair<Long, Boolean>(null, false);
final Resources res = getResources();
final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale);
final Long dictionaryId = DictionaryFactory.getDictionaryId(this, locale);
boolean hasLayout = false;
try {
final String localeStr = locale.toString();
final String[] layoutCountryCodes = KeyboardSet.parseKeyboardLocale(
getResources(), R.xml.keyboard_set).split(",", -1);
if (!TextUtils.isEmpty(localeStr) && layoutCountryCodes.length > 0) {
for (String s : layoutCountryCodes) {
if (s.equals(localeStr)) {
hasLayout = true;
break;
}
}
}
} catch (XmlPullParserException e) {
} catch (IOException e) {
}
LocaleUtils.setSystemLocale(res, saveLocale);
return new Pair<Long, Boolean>(dictionaryId, hasLayout);
}
private String get5Code(Locale locale) {
String country = locale.getCountry();
return locale.getLanguage()
+ (TextUtils.isEmpty(country) ? "" : "_" + country);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
// Save the selected languages
String checkedLanguages = "";
PreferenceGroup parent = getPreferenceScreen();
int count = parent.getPreferenceCount();
for (int i = 0; i < count; i++) {
CheckBoxPreference pref = (CheckBoxPreference) parent.getPreference(i);
if (pref.isChecked()) {
checkedLanguages += get5Code(mLocaleMap.get(pref)) + ",";
}
}
if (checkedLanguages.length() < 1) checkedLanguages = null; // Save null
Editor editor = mPrefs.edit();
editor.putString(Settings.PREF_SELECTED_LANGUAGES, checkedLanguages);
SharedPreferencesCompat.apply(editor);
}
public ArrayList<LocaleEntry> getUniqueLocales() {
String[] locales = getAssets().getLocales();
Arrays.sort(locales);
ArrayList<LocaleEntry> uniqueLocales = new ArrayList<LocaleEntry>();
final int origSize = locales.length;
LocaleEntry[] preprocess = new LocaleEntry[origSize];
int finalSize = 0;
for (int i = 0 ; i < origSize; i++ ) {
String s = locales[i];
int len = s.length();
String language = "";
String country = "";
if (len == 5) {
language = s.substring(0, 2);
country = s.substring(3, 5);
} else if (len < 5) {
language = s;
}
Locale l = new Locale(language, country);
// Exclude languages that are not relevant to LatinIME
if (TextUtils.isEmpty(language)) {
continue;
}
if (finalSize == 0) {
preprocess[finalSize++] =
new LocaleEntry(StringUtils.getFullDisplayName(l, false), l);
} else {
if (s.equals("zz_ZZ")) {
// ignore this locale
} else {
final String displayName = StringUtils.getFullDisplayName(l, false);
preprocess[finalSize++] = new LocaleEntry(displayName, l);
}
}
}
for (int i = 0; i < finalSize ; i++) {
uniqueLocales.add(preprocess[i]);
}
return uniqueLocales;
}
}

View File

@ -1,234 +0,0 @@
/*
* Copyright (C) 2010 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.languageswitcher;
import com.android.inputmethod.compat.SharedPreferencesCompat;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.Settings;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Configuration;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
import java.util.Locale;
/**
* Keeps track of list of selected input languages and the current
* input language that the user has selected.
*/
public class LanguageSwitcher {
private static final String TAG = LanguageSwitcher.class.getSimpleName();
@SuppressWarnings("unused")
private static final String KEYBOARD_MODE = "keyboard";
private static final String[] EMPTY_STIRNG_ARRAY = new String[0];
private final ArrayList<Locale> mLocales = new ArrayList<Locale>();
private final LatinIME mIme;
private String[] mSelectedLanguageArray = EMPTY_STIRNG_ARRAY;
private String mSelectedLanguages;
private int mCurrentIndex = 0;
private String mDefaultInputLanguage;
private Locale mDefaultInputLocale;
private Locale mSystemLocale;
public LanguageSwitcher(LatinIME ime) {
mIme = ime;
}
public int getLocaleCount() {
return mLocales.size();
}
public void onConfigurationChanged(Configuration conf, SharedPreferences prefs) {
final Locale newLocale = conf.locale;
if (!getSystemLocale().toString().equals(newLocale.toString())) {
loadLocales(prefs, newLocale);
}
}
/**
* Loads the currently selected input languages from shared preferences.
* @param sp shared preference for getting the current input language and enabled languages
* @param systemLocale the current system locale, stored for changing the current input language
* based on the system current system locale.
* @return whether there was any change
*/
public boolean loadLocales(SharedPreferences sp, Locale systemLocale) {
if (LatinImeLogger.sDBG) {
Log.d(TAG, "load locales");
}
if (systemLocale != null) {
setSystemLocale(systemLocale);
}
String selectedLanguages = sp.getString(Settings.PREF_SELECTED_LANGUAGES, null);
String currentLanguage = sp.getString(Settings.PREF_INPUT_LANGUAGE, null);
if (TextUtils.isEmpty(selectedLanguages)) {
mSelectedLanguageArray = EMPTY_STIRNG_ARRAY;
mSelectedLanguages = null;
loadDefaults();
if (mLocales.size() == 0) {
return false;
}
mLocales.clear();
return true;
}
if (selectedLanguages.equals(mSelectedLanguages)) {
return false;
}
mSelectedLanguageArray = selectedLanguages.split(",");
mSelectedLanguages = selectedLanguages; // Cache it for comparison later
constructLocales();
mCurrentIndex = 0;
if (currentLanguage != null) {
// Find the index
mCurrentIndex = 0;
for (int i = 0; i < mLocales.size(); i++) {
if (mSelectedLanguageArray[i].equals(currentLanguage)) {
mCurrentIndex = i;
break;
}
}
// If we didn't find the index, use the first one
}
return true;
}
private void loadDefaults() {
if (LatinImeLogger.sDBG) {
Log.d(TAG, "load default locales:");
}
mDefaultInputLocale = mIme.getResources().getConfiguration().locale;
String country = mDefaultInputLocale.getCountry();
mDefaultInputLanguage = mDefaultInputLocale.getLanguage() +
(TextUtils.isEmpty(country) ? "" : "_" + country);
}
private void constructLocales() {
mLocales.clear();
for (final String lang : mSelectedLanguageArray) {
final Locale locale = LocaleUtils.constructLocaleFromString(lang);
mLocales.add(locale);
}
}
/**
* Returns the currently selected input language code, or the display language code if
* no specific locale was selected for input.
*/
public String getInputLanguage() {
if (getLocaleCount() == 0) return mDefaultInputLanguage;
return mSelectedLanguageArray[mCurrentIndex];
}
/**
* Returns the list of enabled language codes.
*/
public String[] getEnabledLanguages(boolean allowImplicitlySelectedLanguages) {
if (mSelectedLanguageArray.length == 0 && allowImplicitlySelectedLanguages) {
return new String[] { mDefaultInputLanguage };
}
return mSelectedLanguageArray;
}
/**
* Returns the currently selected input locale, or the display locale if no specific
* locale was selected for input.
*/
public Locale getInputLocale() {
if (getLocaleCount() == 0) return mDefaultInputLocale;
return mLocales.get(mCurrentIndex);
}
private int nextLocaleIndex() {
final int size = mLocales.size();
return (mCurrentIndex + 1) % size;
}
private int prevLocaleIndex() {
final int size = mLocales.size();
return (mCurrentIndex - 1 + size) % size;
}
/**
* Returns the next input locale in the list. Wraps around to the beginning of the
* list if we're at the end of the list.
*/
public Locale getNextInputLocale() {
if (getLocaleCount() == 0) return mDefaultInputLocale;
return mLocales.get(nextLocaleIndex());
}
/**
* Sets the system locale (display UI) used for comparing with the input language.
* @param locale the locale of the system
*/
private void setSystemLocale(Locale locale) {
mSystemLocale = locale;
}
/**
* Returns the system locale.
* @return the system locale
*/
private Locale getSystemLocale() {
return mSystemLocale;
}
/**
* Returns the previous input locale in the list. Wraps around to the end of the
* list if we're at the beginning of the list.
*/
public Locale getPrevInputLocale() {
if (getLocaleCount() == 0) return mDefaultInputLocale;
return mLocales.get(prevLocaleIndex());
}
public void reset() {
mCurrentIndex = 0;
}
public void next() {
mCurrentIndex = nextLocaleIndex();
}
public void prev() {
mCurrentIndex = prevLocaleIndex();
}
public void setLocale(String localeStr) {
final int N = mLocales.size();
for (int i = 0; i < N; ++i) {
if (mLocales.get(i).toString().equals(localeStr)) {
mCurrentIndex = i;
}
}
}
public void persist(SharedPreferences prefs) {
Editor editor = prefs.edit();
editor.putString(Settings.PREF_INPUT_LANGUAGE, getInputLanguage());
SharedPreferencesCompat.apply(editor);
}
}

View File

@ -1,104 +0,0 @@
/*
* Copyright (C) 2009 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.voice;
import android.os.Bundle;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
/**
* Represents information about a given text field, which can be passed
* to the speech recognizer as context information.
*/
public class FieldContext {
private static final boolean DBG = false;
static final String LABEL = "label";
static final String HINT = "hint";
static final String PACKAGE_NAME = "packageName";
static final String FIELD_ID = "fieldId";
static final String FIELD_NAME = "fieldName";
static final String SINGLE_LINE = "singleLine";
static final String INPUT_TYPE = "inputType";
static final String IME_OPTIONS = "imeOptions";
static final String SELECTED_LANGUAGE = "selectedLanguage";
static final String ENABLED_LANGUAGES = "enabledLanguages";
Bundle mFieldInfo;
public FieldContext(InputConnection conn, EditorInfo editorInfo,
String selectedLanguage, String[] enabledLanguages) {
mFieldInfo = new Bundle();
addEditorInfoToBundle(editorInfo, mFieldInfo);
addInputConnectionToBundle(conn, mFieldInfo);
addLanguageInfoToBundle(selectedLanguage, enabledLanguages, mFieldInfo);
if (DBG) Log.i("FieldContext", "Bundle = " + mFieldInfo.toString());
}
private static String safeToString(Object o) {
if (o == null) {
return "";
}
return o.toString();
}
private static void addEditorInfoToBundle(EditorInfo info, Bundle bundle) {
if (info == null) {
return;
}
bundle.putString(LABEL, safeToString(info.label));
bundle.putString(HINT, safeToString(info.hintText));
bundle.putString(PACKAGE_NAME, safeToString(info.packageName));
bundle.putInt(FIELD_ID, info.fieldId);
bundle.putString(FIELD_NAME, safeToString(info.fieldName));
bundle.putInt(INPUT_TYPE, info.inputType);
bundle.putInt(IME_OPTIONS, info.imeOptions);
}
@SuppressWarnings("static-access")
private static void addInputConnectionToBundle(
InputConnection conn, Bundle bundle) {
if (conn == null) {
return;
}
ExtractedText et = conn.getExtractedText(new ExtractedTextRequest(), 0);
if (et == null) {
return;
}
bundle.putBoolean(SINGLE_LINE, (et.flags & et.FLAG_SINGLE_LINE) > 0);
}
private static void addLanguageInfoToBundle(
String selectedLanguage, String[] enabledLanguages, Bundle bundle) {
bundle.putString(SELECTED_LANGUAGE, selectedLanguage);
bundle.putStringArray(ENABLED_LANGUAGES, enabledLanguages);
}
public Bundle getBundle() {
return mFieldInfo;
}
@Override
public String toString() {
return mFieldInfo.toString();
}
}

View File

@ -1,188 +0,0 @@
/*
* Copyright (C) 2009 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.voice;
import com.android.inputmethod.compat.SharedPreferencesCompat;
import com.android.inputmethod.latin.R;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.view.inputmethod.InputConnection;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
/**
* Logic to determine when to display hints on usage to the user.
*/
public class Hints {
public interface Display {
public void showHint(int viewResource);
}
private static final String PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN =
"voice_hint_num_unique_days_shown";
private static final String PREF_VOICE_HINT_LAST_TIME_SHOWN =
"voice_hint_last_time_shown";
private static final String PREF_VOICE_INPUT_LAST_TIME_USED =
"voice_input_last_time_used";
private static final String PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT =
"voice_punctuation_hint_view_count";
private static final int DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW = 7;
private static final int DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS = 7;
private final Context mContext;
private final SharedPreferences mPrefs;
private final Display mDisplay;
private boolean mVoiceResultContainedPunctuation;
private int mSwipeHintMaxDaysToShow;
private int mPunctuationHintMaxDisplays;
// Only show punctuation hint if voice result did not contain punctuation.
static final Map<CharSequence, String> SPEAKABLE_PUNCTUATION
= new HashMap<CharSequence, String>();
static {
SPEAKABLE_PUNCTUATION.put(",", "comma");
SPEAKABLE_PUNCTUATION.put(".", "period");
SPEAKABLE_PUNCTUATION.put("?", "question mark");
}
public Hints(Context context, SharedPreferences prefs, Display display) {
mContext = context;
mPrefs = prefs;
mDisplay = display;
ContentResolver cr = mContext.getContentResolver();
mSwipeHintMaxDaysToShow = SettingsUtil.getSettingsInt(
cr,
SettingsUtil.LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS,
DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW);
mPunctuationHintMaxDisplays = SettingsUtil.getSettingsInt(
cr,
SettingsUtil.LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS,
DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS);
}
public boolean showSwipeHintIfNecessary(boolean fieldRecommended) {
if (fieldRecommended && shouldShowSwipeHint()) {
showHint(R.layout.voice_swipe_hint);
return true;
}
return false;
}
public boolean showPunctuationHintIfNecessary(InputConnection ic) {
if (!mVoiceResultContainedPunctuation
&& ic != null
&& getAndIncrementPref(PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT)
< mPunctuationHintMaxDisplays) {
CharSequence charBeforeCursor = ic.getTextBeforeCursor(1, 0);
if (SPEAKABLE_PUNCTUATION.containsKey(charBeforeCursor)) {
showHint(R.layout.voice_punctuation_hint);
return true;
}
}
return false;
}
public void registerVoiceResult(String text) {
// Update the current time as the last time voice input was used.
SharedPreferences.Editor editor = mPrefs.edit();
editor.putLong(PREF_VOICE_INPUT_LAST_TIME_USED, System.currentTimeMillis());
SharedPreferencesCompat.apply(editor);
mVoiceResultContainedPunctuation = false;
for (CharSequence s : SPEAKABLE_PUNCTUATION.keySet()) {
if (text.indexOf(s.toString()) >= 0) {
mVoiceResultContainedPunctuation = true;
break;
}
}
}
private boolean shouldShowSwipeHint() {
final SharedPreferences prefs = mPrefs;
int numUniqueDaysShown = prefs.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0);
// If we've already shown the hint for enough days, we'll return false.
if (numUniqueDaysShown < mSwipeHintMaxDaysToShow) {
long lastTimeVoiceWasUsed = prefs.getLong(PREF_VOICE_INPUT_LAST_TIME_USED, 0);
// If the user has used voice today, we'll return false. (We don't show the hint on
// any day that the user has already used voice.)
if (!isFromToday(lastTimeVoiceWasUsed)) {
return true;
}
}
return false;
}
/**
* Determines whether the provided time is from some time today (i.e., this day, month,
* and year).
*/
private boolean isFromToday(long timeInMillis) {
if (timeInMillis == 0) return false;
Calendar today = Calendar.getInstance();
today.setTimeInMillis(System.currentTimeMillis());
Calendar timestamp = Calendar.getInstance();
timestamp.setTimeInMillis(timeInMillis);
return (today.get(Calendar.YEAR) == timestamp.get(Calendar.YEAR) &&
today.get(Calendar.DAY_OF_MONTH) == timestamp.get(Calendar.DAY_OF_MONTH) &&
today.get(Calendar.MONTH) == timestamp.get(Calendar.MONTH));
}
private void showHint(int hintViewResource) {
final SharedPreferences prefs = mPrefs;
int numUniqueDaysShown = prefs.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0);
long lastTimeHintWasShown = prefs.getLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, 0);
// If this is the first time the hint is being shown today, increase the saved values
// to represent that. We don't need to increase the last time the hint was shown unless
// it is a different day from the current value.
if (!isFromToday(lastTimeHintWasShown)) {
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, numUniqueDaysShown + 1);
editor.putLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, System.currentTimeMillis());
SharedPreferencesCompat.apply(editor);
}
if (mDisplay != null) {
mDisplay.showHint(hintViewResource);
}
}
private int getAndIncrementPref(String pref) {
final SharedPreferences prefs = mPrefs;
int value = prefs.getInt(pref, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(pref, value + 1);
SharedPreferencesCompat.apply(editor);
return value;
}
}

View File

@ -1,355 +0,0 @@
/*
* Copyright (C) 2009 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.voice;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StringUtils;
import com.android.inputmethod.latin.SubtypeSwitcher;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.Locale;
/**
* The user interface for the "Speak now" and "working" states.
* Displays a recognition dialog (with waveform, voice meter, etc.),
* plays beeps, shows errors, etc.
*/
public class RecognitionView {
private static final String TAG = "RecognitionView";
private Handler mUiHandler; // Reference to UI thread
private View mView;
private Context mContext;
private TextView mText;
private ImageView mImage;
private View mProgress;
private SoundIndicator mSoundIndicator;
private TextView mLanguage;
private Button mButton;
private Drawable mInitializing;
private Drawable mError;
private static final int INIT = 0;
private static final int LISTENING = 1;
private static final int WORKING = 2;
private static final int READY = 3;
private int mState = INIT;
private final View mPopupLayout;
private final Drawable mListeningBorder;
private final Drawable mWorkingBorder;
private final Drawable mErrorBorder;
public RecognitionView(Context context, OnClickListener clickListener) {
mUiHandler = new Handler();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mView = inflater.inflate(R.layout.recognition_status, null);
mPopupLayout= mView.findViewById(R.id.popup_layout);
// Pre-load volume level images
Resources r = context.getResources();
mListeningBorder = r.getDrawable(R.drawable.vs_dialog_red);
mWorkingBorder = r.getDrawable(R.drawable.vs_dialog_blue);
mErrorBorder = r.getDrawable(R.drawable.vs_dialog_yellow);
mInitializing = r.getDrawable(R.drawable.mic_slash);
mError = r.getDrawable(R.drawable.caution);
mImage = (ImageView) mView.findViewById(R.id.image);
mProgress = mView.findViewById(R.id.progress);
mSoundIndicator = (SoundIndicator) mView.findViewById(R.id.sound_indicator);
mButton = (Button) mView.findViewById(R.id.button);
mButton.setOnClickListener(clickListener);
mText = (TextView) mView.findViewById(R.id.text);
mLanguage = (TextView) mView.findViewById(R.id.language);
mContext = context;
}
public View getView() {
return mView;
}
public void restoreState() {
mUiHandler.post(new Runnable() {
@Override
public void run() {
// Restart the spinner
if (mState == WORKING) {
((ProgressBar) mProgress).setIndeterminate(false);
((ProgressBar) mProgress).setIndeterminate(true);
}
}
});
}
public void showInitializing() {
mUiHandler.post(new Runnable() {
@Override
public void run() {
mState = INIT;
prepareDialog(mContext.getText(R.string.voice_initializing), mInitializing,
mContext.getText(R.string.cancel));
}
});
}
public void showListening() {
Log.d(TAG, "#showListening");
mUiHandler.post(new Runnable() {
@Override
public void run() {
mState = LISTENING;
prepareDialog(mContext.getText(R.string.voice_listening), null,
mContext.getText(R.string.cancel));
}
});
}
public void updateVoiceMeter(float rmsdB) {
mSoundIndicator.setRmsdB(rmsdB);
}
public void showError(final String message) {
mUiHandler.post(new Runnable() {
@Override
public void run() {
mState = READY;
prepareDialog(message, mError, mContext.getText(R.string.ok));
}
});
}
public void showWorking(
final ByteArrayOutputStream waveBuffer,
final int speechStartPosition,
final int speechEndPosition) {
mUiHandler.post(new Runnable() {
@Override
public void run() {
mState = WORKING;
prepareDialog(mContext.getText(R.string.voice_working), null, mContext
.getText(R.string.cancel));
final ShortBuffer buf = ByteBuffer.wrap(waveBuffer.toByteArray()).order(
ByteOrder.nativeOrder()).asShortBuffer();
buf.position(0);
waveBuffer.reset();
showWave(buf, speechStartPosition / 2, speechEndPosition / 2);
}
});
}
private void prepareDialog(CharSequence text, Drawable image,
CharSequence btnTxt) {
/*
* The mic of INIT and of LISTENING has to be displayed in the same position. To accomplish
* that, some text visibility are not set as GONE but as INVISIBLE.
*/
switch (mState) {
case INIT:
mText.setVisibility(View.INVISIBLE);
mProgress.setVisibility(View.GONE);
mImage.setVisibility(View.VISIBLE);
mImage.setImageResource(R.drawable.mic_slash);
mSoundIndicator.setVisibility(View.GONE);
mSoundIndicator.stop();
mLanguage.setVisibility(View.INVISIBLE);
mPopupLayout.setBackgroundDrawable(mListeningBorder);
break;
case LISTENING:
mText.setVisibility(View.VISIBLE);
mText.setText(text);
mProgress.setVisibility(View.GONE);
mImage.setVisibility(View.GONE);
mSoundIndicator.setVisibility(View.VISIBLE);
mSoundIndicator.start();
Locale locale = SubtypeSwitcher.getInstance().getInputLocale();
mLanguage.setVisibility(View.VISIBLE);
mLanguage.setText(StringUtils.getFullDisplayName(locale, true));
mPopupLayout.setBackgroundDrawable(mListeningBorder);
break;
case WORKING:
mText.setVisibility(View.VISIBLE);
mText.setText(text);
mProgress.setVisibility(View.VISIBLE);
mImage.setVisibility(View.VISIBLE);
mSoundIndicator.setVisibility(View.GONE);
mSoundIndicator.stop();
mLanguage.setVisibility(View.GONE);
mPopupLayout.setBackgroundDrawable(mWorkingBorder);
break;
case READY:
mText.setVisibility(View.VISIBLE);
mText.setText(text);
mProgress.setVisibility(View.GONE);
mImage.setVisibility(View.VISIBLE);
mImage.setImageResource(R.drawable.caution);
mSoundIndicator.setVisibility(View.GONE);
mSoundIndicator.stop();
mLanguage.setVisibility(View.GONE);
mPopupLayout.setBackgroundDrawable(mErrorBorder);
break;
default:
Log.w(TAG, "Unknown state " + mState);
}
mPopupLayout.requestLayout();
mButton.setText(btnTxt);
}
/**
* @return an average abs of the specified buffer.
*/
private static int getAverageAbs(ShortBuffer buffer, int start, int i, int npw) {
int from = start + i * npw;
int end = from + npw;
int total = 0;
for (int x = from; x < end; x++) {
total += Math.abs(buffer.get(x));
}
return total / npw;
}
/**
* Shows waveform of input audio.
*
* Copied from version in VoiceSearch's RecognitionActivity.
*
* TODO: adjust stroke width based on the size of data.
* TODO: use dip rather than pixels.
*/
private void showWave(ShortBuffer waveBuffer, int startPosition, int endPosition) {
final int w = ((View) mImage.getParent()).getWidth();
final int h = ((View) mImage.getParent()).getHeight();
if (w <= 0 || h <= 0) {
// view is not visible this time. Skip drawing.
return;
}
final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(b);
final Paint paint = new Paint();
paint.setColor(0xFFFFFFFF); // 0xAARRGGBB
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setAlpha(80);
final PathEffect effect = new CornerPathEffect(3);
paint.setPathEffect(effect);
final int numSamples = waveBuffer.remaining();
int endIndex;
if (endPosition == 0) {
endIndex = numSamples;
} else {
endIndex = Math.min(endPosition, numSamples);
}
int startIndex = startPosition - 2000; // include 250ms before speech
if (startIndex < 0) {
startIndex = 0;
}
final int numSamplePerWave = 200; // 8KHz 25ms = 200 samples
final float scale = 10.0f / 65536.0f;
final int count = (endIndex - startIndex) / numSamplePerWave;
final float deltaX = 1.0f * w / count;
int yMax = h / 2;
Path path = new Path();
c.translate(0, yMax);
float x = 0;
path.moveTo(x, 0);
for (int i = 0; i < count; i++) {
final int avabs = getAverageAbs(waveBuffer, startIndex, i , numSamplePerWave);
int sign = ( (i & 01) == 0) ? -1 : 1;
final float y = Math.min(yMax, avabs * h * scale) * sign;
path.lineTo(x, y);
x += deltaX;
path.lineTo(x, y);
}
if (deltaX > 4) {
paint.setStrokeWidth(2);
} else {
paint.setStrokeWidth(Math.max(0, (int) (deltaX -.05)));
}
c.drawPath(path, paint);
mImage.setImageBitmap(b);
}
public void finish() {
mUiHandler.post(new Runnable() {
@Override
public void run() {
mSoundIndicator.stop();
}
});
}
}

View File

@ -1,110 +0,0 @@
/*
* Copyright (C) 2009 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.voice;
import android.content.ContentResolver;
import android.provider.Settings;
/**
* Utility for retrieving settings from Settings.Secure.
*/
public class SettingsUtil {
/**
* A whitespace-separated list of supported locales for voice input from the keyboard.
*/
public static final String LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES =
"latin_ime_voice_input_supported_locales";
/**
* A whitespace-separated list of recommended app packages for voice input from the
* keyboard.
*/
public static final String LATIN_IME_VOICE_INPUT_RECOMMENDED_PACKAGES =
"latin_ime_voice_input_recommended_packages";
/**
* The maximum number of unique days to show the swipe hint for voice input.
*/
public static final String LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS =
"latin_ime_voice_input_swipe_hint_max_days";
/**
* The maximum number of times to show the punctuation hint for voice input.
*/
public static final String LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS =
"latin_ime_voice_input_punctuation_hint_max_displays";
/**
* Endpointer parameters for voice input from the keyboard.
*/
public static final String LATIN_IME_SPEECH_MINIMUM_LENGTH_MILLIS =
"latin_ime_speech_minimum_length_millis";
public static final String LATIN_IME_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS =
"latin_ime_speech_input_complete_silence_length_millis";
public static final String LATIN_IME_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS =
"latin_ime_speech_input_possibly_complete_silence_length_millis";
/**
* Min and max volume levels that can be displayed on the "speak now" screen.
*/
public static final String LATIN_IME_MIN_MICROPHONE_LEVEL =
"latin_ime_min_microphone_level";
public static final String LATIN_IME_MAX_MICROPHONE_LEVEL =
"latin_ime_max_microphone_level";
/**
* The number of sentence-level alternates to request of the server.
*/
public static final String LATIN_IME_MAX_VOICE_RESULTS = "latin_ime_max_voice_results";
/**
* Get a string-valued setting.
*
* @param cr The content resolver to use
* @param key The setting to look up
* @param defaultValue The default value to use if none can be found
* @return The value of the setting, or defaultValue if it couldn't be found
*/
public static String getSettingsString(ContentResolver cr, String key, String defaultValue) {
String result = Settings.Secure.getString(cr, key);
return (result == null) ? defaultValue : result;
}
/**
* Get an int-valued setting.
*
* @param cr The content resolver to use
* @param key The setting to look up
* @param defaultValue The default value to use if the setting couldn't be found or parsed
* @return The value of the setting, or defaultValue if it couldn't be found or parsed
*/
public static int getSettingsInt(ContentResolver cr, String key, int defaultValue) {
return Settings.Secure.getInt(cr, key, defaultValue);
}
/**
* Get a float-valued setting.
*
* @param cr The content resolver to use
* @param key The setting to look up
* @param defaultValue The default value to use if the setting couldn't be found or parsed
* @return The value of the setting, or defaultValue if it couldn't be found or parsed
*/
public static float getSettingsFloat(ContentResolver cr, String key, float defaultValue) {
return Settings.Secure.getFloat(cr, key, defaultValue);
}
}

View File

@ -1,155 +0,0 @@
/*
* Copyright (C) 2011 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.voice;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.android.inputmethod.latin.R;
/**
* A widget which shows the volume of audio using a microphone icon
*/
public class SoundIndicator extends ImageView {
@SuppressWarnings("unused")
private static final String TAG = "SoundIndicator";
private static final float UP_SMOOTHING_FACTOR = 0.9f;
private static final float DOWN_SMOOTHING_FACTOR = 0.4f;
private static final float AUDIO_METER_MIN_DB = 7.0f;
private static final float AUDIO_METER_DB_RANGE = 20.0f;
private static final long FRAME_DELAY = 50;
private Bitmap mDrawingBuffer;
private Canvas mBufferCanvas;
private Bitmap mEdgeBitmap;
private float mLevel = 0.0f;
private Drawable mFrontDrawable;
private Paint mClearPaint;
private Paint mMultPaint;
private int mEdgeBitmapOffset;
private Handler mHandler;
private Runnable mDrawFrame = new Runnable() {
public void run() {
invalidate();
mHandler.postDelayed(mDrawFrame, FRAME_DELAY);
}
};
public SoundIndicator(Context context) {
this(context, null);
}
public SoundIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
mFrontDrawable = getDrawable();
BitmapDrawable edgeDrawable =
(BitmapDrawable) context.getResources().getDrawable(R.drawable.vs_popup_mic_edge);
mEdgeBitmap = edgeDrawable.getBitmap();
mEdgeBitmapOffset = mEdgeBitmap.getHeight() / 2;
mDrawingBuffer =
Bitmap.createBitmap(mFrontDrawable.getIntrinsicWidth(),
mFrontDrawable.getIntrinsicHeight(), Config.ARGB_8888);
mBufferCanvas = new Canvas(mDrawingBuffer);
// Initialize Paints.
mClearPaint = new Paint();
mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mMultPaint = new Paint();
mMultPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
mHandler = new Handler();
}
@Override
public void onDraw(Canvas canvas) {
//super.onDraw(canvas);
float w = getWidth();
float h = getHeight();
// Clear the buffer canvas
mBufferCanvas.drawRect(0, 0, w, h, mClearPaint);
// Set its clip so we don't draw the front image all the way to the top
Rect clip = new Rect(0,
(int) ((1.0 - mLevel) * (h + mEdgeBitmapOffset)) - mEdgeBitmapOffset,
(int) w,
(int) h);
mBufferCanvas.save();
mBufferCanvas.clipRect(clip);
// Draw the front image
mFrontDrawable.setBounds(new Rect(0, 0, (int) w, (int) h));
mFrontDrawable.draw(mBufferCanvas);
mBufferCanvas.restore();
// Draw the edge image on top of the buffer image with a multiply mode
mBufferCanvas.drawBitmap(mEdgeBitmap, 0, clip.top, mMultPaint);
// Draw the buffer image (on top of the background image)
canvas.drawBitmap(mDrawingBuffer, 0, 0, null);
}
/**
* Sets the sound level
*
* @param rmsdB The level of the sound, in dB.
*/
public void setRmsdB(float rmsdB) {
float level = ((rmsdB - AUDIO_METER_MIN_DB) / AUDIO_METER_DB_RANGE);
level = Math.min(Math.max(0.0f, level), 1.0f);
// We smooth towards the new level
if (level > mLevel) {
mLevel = (level - mLevel) * UP_SMOOTHING_FACTOR + mLevel;
} else {
mLevel = (level - mLevel) * DOWN_SMOOTHING_FACTOR + mLevel;
}
invalidate();
}
public void start() {
mHandler.post(mDrawFrame);
}
public void stop() {
mHandler.removeCallbacks(mDrawFrame);
}
}

View File

@ -1,692 +0,0 @@
/*
* Copyright (C) 2009 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.voice;
import com.android.inputmethod.latin.EditingUtils;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.os.Parcelable;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputConnection;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* Speech recognition input, including both user interface and a background
* process to stream audio to the network recognizer. This class supplies a
* View (getView()), which it updates as recognition occurs. The user of this
* class is responsible for making the view visible to the user, as well as
* handling various events returned through UiListener.
*/
public class VoiceInput implements OnClickListener {
private static final String TAG = "VoiceInput";
private static final String EXTRA_RECOGNITION_CONTEXT =
"android.speech.extras.RECOGNITION_CONTEXT";
private static final String EXTRA_CALLING_PACKAGE = "calling_package";
private static final String EXTRA_ALTERNATES = "android.speech.extra.ALTERNATES";
private static final int MAX_ALT_LIST_LENGTH = 6;
private static boolean DBG = LatinImeLogger.sDBG;
private static final String DEFAULT_RECOMMENDED_PACKAGES =
"com.android.mms " +
"com.google.android.gm " +
"com.google.android.talk " +
"com.google.android.apps.googlevoice " +
"com.android.email " +
"com.android.browser ";
// WARNING! Before enabling this, fix the problem with calling getExtractedText() in
// landscape view. It causes Extracted text updates to be rejected due to a token mismatch
public static boolean ENABLE_WORD_CORRECTIONS = true;
// Dummy word suggestion which means "delete current word"
public static final String DELETE_SYMBOL = " \u00D7 "; // times symbol
private Whitelist mRecommendedList;
private Whitelist mBlacklist;
private VoiceInputLogger mLogger;
// Names of a few extras defined in VoiceSearch's RecognitionController
// Note, the version of voicesearch that shipped in Froyo returns the raw
// RecognitionClientAlternates protocol buffer under the key "alternates",
// so a VS market update must be installed on Froyo devices in order to see
// alternatives.
private static final String ALTERNATES_BUNDLE = "alternates_bundle";
// This is copied from the VoiceSearch app.
@SuppressWarnings("unused")
private static final class AlternatesBundleKeys {
public static final String ALTERNATES = "alternates";
public static final String CONFIDENCE = "confidence";
public static final String LENGTH = "length";
public static final String MAX_SPAN_LENGTH = "max_span_length";
public static final String SPANS = "spans";
public static final String SPAN_KEY_DELIMITER = ":";
public static final String START = "start";
public static final String TEXT = "text";
}
// Names of a few intent extras defined in VoiceSearch's RecognitionService.
// These let us tweak the endpointer parameters.
private static final String EXTRA_SPEECH_MINIMUM_LENGTH_MILLIS =
"android.speech.extras.SPEECH_INPUT_MINIMUM_LENGTH_MILLIS";
private static final String EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS =
"android.speech.extras.SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS";
private static final String EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS =
"android.speech.extras.SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS";
// The usual endpointer default value for input complete silence length is 0.5 seconds,
// but that's used for things like voice search. For dictation-like voice input like this,
// we go with a more liberal value of 1 second. This value will only be used if a value
// is not provided from Gservices.
private static final String INPUT_COMPLETE_SILENCE_LENGTH_DEFAULT_VALUE_MILLIS = "1000";
// Used to record part of that state for logging purposes.
public static final int DEFAULT = 0;
public static final int LISTENING = 1;
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_RESET = 1;
private final UIHandler mHandler = new UIHandler(this);
private static class UIHandler extends StaticInnerHandlerWrapper<VoiceInput> {
public UIHandler(VoiceInput outerInstance) {
super(outerInstance);
}
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_RESET) {
final VoiceInput voiceInput = getOuterInstance();
voiceInput.mState = DEFAULT;
voiceInput.mRecognitionView.finish();
voiceInput.mUiListener.onCancelVoice();
}
}
};
/**
* Events relating to the recognition UI. You must implement these.
*/
public interface UiListener {
/**
* @param recognitionResults a set of transcripts for what the user
* spoke, sorted by likelihood.
*/
public void onVoiceResults(
List<String> recognitionResults,
Map<String, List<CharSequence>> alternatives);
/**
* Called when the user cancels speech recognition.
*/
public void onCancelVoice();
}
private SpeechRecognizer mSpeechRecognizer;
private RecognitionListener mRecognitionListener;
private RecognitionView mRecognitionView;
private UiListener mUiListener;
private Context mContext;
/**
* @param context the service or activity in which we're running.
* @param uiHandler object to receive events from VoiceInput.
*/
public VoiceInput(Context context, UiListener uiHandler) {
mLogger = VoiceInputLogger.getLogger(context);
mRecognitionListener = new ImeRecognitionListener();
mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(context);
mSpeechRecognizer.setRecognitionListener(mRecognitionListener);
mUiListener = uiHandler;
mContext = context;
newView();
String recommendedPackages = SettingsUtil.getSettingsString(
context.getContentResolver(),
SettingsUtil.LATIN_IME_VOICE_INPUT_RECOMMENDED_PACKAGES,
DEFAULT_RECOMMENDED_PACKAGES);
mRecommendedList = new Whitelist();
for (String recommendedPackage : recommendedPackages.split("\\s+")) {
mRecommendedList.addApp(recommendedPackage);
}
mBlacklist = new Whitelist();
mBlacklist.addApp("com.google.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 += count;
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.
*/
public void onConfigurationChanged(Configuration configuration) {
mRecognitionView.restoreState();
mRecognitionView.getView().dispatchConfigurationChanged(configuration);
}
/**
* @return true if field is blacklisted for voice
*/
public boolean isBlacklistedField(FieldContext context) {
return mBlacklist.matches(context);
}
/**
* Used to decide whether to show voice input hints for this field, etc.
*
* @return true if field is recommended for voice
*/
public boolean isRecommendedField(FieldContext context) {
return mRecommendedList.matches(context);
}
/**
* Start listening for speech from the user. This will grab the microphone
* and start updating the view provided by getView(). It is the caller's
* responsibility to ensure that the view is visible to the user at this stage.
*
* @param context the same FieldContext supplied to voiceIsEnabled()
* @param swipe whether this voice input was started by swipe, for logging purposes
*/
public void startListening(FieldContext context, boolean swipe) {
if (DBG) {
Log.d(TAG, "startListening: " + context);
}
if (mState != DEFAULT) {
Log.w(TAG, "startListening in the wrong status " + mState);
}
// If everything works ok, the voice input should be already in the correct state. As this
// class can be called by third-party, we call reset just to be on the safe side.
reset();
Locale locale = Locale.getDefault();
String localeString = locale.getLanguage() + "-" + locale.getCountry();
mLogger.start(localeString, swipe);
mState = LISTENING;
mRecognitionView.showInitializing();
startListeningAfterInitialization(context);
}
/**
* Called only when the recognition manager's initialization completed
*
* @param context context with which {@link #startListening(FieldContext, boolean)} was executed
*/
private void startListeningAfterInitialization(FieldContext context) {
Intent intent = makeIntent();
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "");
intent.putExtra(EXTRA_RECOGNITION_CONTEXT, context.getBundle());
intent.putExtra(EXTRA_CALLING_PACKAGE, "VoiceIME");
intent.putExtra(EXTRA_ALTERNATES, true);
intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS,
SettingsUtil.getSettingsInt(
mContext.getContentResolver(),
SettingsUtil.LATIN_IME_MAX_VOICE_RESULTS,
1));
// Get endpointer params from Gservices.
// TODO: Consider caching these values for improved performance on slower devices.
final ContentResolver cr = mContext.getContentResolver();
putEndpointerExtra(
cr,
intent,
SettingsUtil.LATIN_IME_SPEECH_MINIMUM_LENGTH_MILLIS,
EXTRA_SPEECH_MINIMUM_LENGTH_MILLIS,
null /* rely on endpointer default */);
putEndpointerExtra(
cr,
intent,
SettingsUtil.LATIN_IME_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,
EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,
INPUT_COMPLETE_SILENCE_LENGTH_DEFAULT_VALUE_MILLIS
/* our default value is different from the endpointer's */);
putEndpointerExtra(
cr,
intent,
SettingsUtil.
LATIN_IME_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS,
EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS,
null /* rely on endpointer default */);
mSpeechRecognizer.startListening(intent);
}
/**
* Gets the value of the provided Gservices key, attempts to parse it into a long,
* and if successful, puts the long value as an extra in the provided intent.
*/
private void putEndpointerExtra(ContentResolver cr, Intent i,
String gservicesKey, String intentExtraKey, String defaultValue) {
long l = -1;
String s = SettingsUtil.getSettingsString(cr, gservicesKey, defaultValue);
if (s != null) {
try {
l = Long.valueOf(s);
} catch (NumberFormatException e) {
Log.e(TAG, "could not parse value for " + gservicesKey + ": " + s);
}
}
if (l != -1) i.putExtra(intentExtraKey, l);
}
public void destroy() {
mSpeechRecognizer.destroy();
}
/**
* Creates a new instance of the view that is returned by {@link #getView()}
* Clients should use this when a previously returned view is stuck in a
* layout that is being thrown away and a new one is need to show to the
* user.
*/
public void newView() {
mRecognitionView = new RecognitionView(mContext, this);
}
/**
* @return a view that shows the recognition flow--e.g., "Speak now" and
* "working" dialogs.
*/
public View getView() {
return mRecognitionView.getView();
}
/**
* Handle the cancel button.
*/
@Override
public void onClick(View view) {
switch(view.getId()) {
case R.id.button:
cancel();
break;
}
}
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(String suggestion, int index,
String wordSeparators, InputConnection ic) {
String wordToBeReplaced = EditingUtils.getWordAtCursor(ic, wordSeparators);
// If we enable phrase-based alternatives, only send up the first word
// in suggestion and wordToBeReplaced.
mLogger.textModifiedByChooseSuggestion(suggestion.length(), wordToBeReplaced.length(),
index, wordToBeReplaced, suggestion);
}
public void logKeyboardWarningDialogShown() {
mLogger.keyboardWarningDialogShown();
}
public void logKeyboardWarningDialogDismissed() {
mLogger.keyboardWarningDialogDismissed();
}
public void logKeyboardWarningDialogOk() {
mLogger.keyboardWarningDialogOk();
}
public void logKeyboardWarningDialogCancel() {
mLogger.keyboardWarningDialogCancel();
}
public void logSwipeHintDisplayed() {
mLogger.swipeHintDisplayed();
}
public void logPunctuationHintDisplayed() {
mLogger.punctuationHintDisplayed();
}
public void logVoiceInputDelivered(int length) {
mLogger.voiceInputDelivered(length);
}
public void logInputEnded() {
mLogger.inputEnded();
}
public void flushLogs() {
mLogger.flush();
}
private static Intent makeIntent() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
// On Cupcake, use VoiceIMEHelper since VoiceSearch doesn't support.
// On Donut, always use VoiceSearch, since VoiceIMEHelper and
// VoiceSearch may conflict.
if (Build.VERSION.RELEASE.equals("1.5")) {
intent = intent.setClassName(
"com.google.android.voiceservice",
"com.google.android.voiceservice.IMERecognitionService");
} else {
intent = intent.setClassName(
"com.google.android.voicesearch",
"com.google.android.voicesearch.RecognitionService");
}
return intent;
}
/**
* Reset the current voice recognition.
*/
public void reset() {
if (mState != DEFAULT) {
mState = DEFAULT;
// Remove all pending tasks (e.g., timers to cancel voice input)
mHandler.removeMessages(MSG_RESET);
mSpeechRecognizer.cancel();
mRecognitionView.finish();
}
}
/**
* Cancel in-progress speech recognition.
*/
public void cancel() {
switch (mState) {
case LISTENING:
mLogger.cancelDuringListening();
break;
case WORKING:
mLogger.cancelDuringWorking();
break;
case ERROR:
mLogger.cancelDuringError();
break;
}
reset();
mUiListener.onCancelVoice();
}
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 SpeechRecognizer.ERROR_CLIENT:
return R.string.voice_not_installed;
case SpeechRecognizer.ERROR_NETWORK:
return R.string.voice_network_error;
case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
return endpointed ?
R.string.voice_network_error : R.string.voice_too_much_speech;
case SpeechRecognizer.ERROR_AUDIO:
return R.string.voice_audio_error;
case SpeechRecognizer.ERROR_SERVER:
return R.string.voice_server_error;
case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
return R.string.voice_speech_timeout;
case SpeechRecognizer.ERROR_NO_MATCH:
return R.string.voice_no_match;
default: return R.string.voice_error;
}
}
private void onError(int errorType, boolean endpointed) {
Log.i(TAG, "error " + errorType);
mLogger.error(errorType);
onError(mContext.getString(getErrorStringId(errorType, endpointed)));
}
private void onError(String error) {
mState = ERROR;
mRecognitionView.showError(error);
// Wait a couple seconds and then automatically dismiss message.
mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_RESET), 2000);
}
private class ImeRecognitionListener implements RecognitionListener {
// Waveform data
final ByteArrayOutputStream mWaveBuffer = new ByteArrayOutputStream();
int mSpeechStart;
private boolean mEndpointed = false;
@Override
public void onReadyForSpeech(Bundle noiseParams) {
mRecognitionView.showListening();
}
@Override
public void onBeginningOfSpeech() {
mEndpointed = false;
mSpeechStart = mWaveBuffer.size();
}
@Override
public void onRmsChanged(float rmsdB) {
mRecognitionView.updateVoiceMeter(rmsdB);
}
@Override
public void onBufferReceived(byte[] buf) {
try {
mWaveBuffer.write(buf);
} catch (IOException e) {
// ignore.
}
}
@Override
public void onEndOfSpeech() {
mEndpointed = true;
mState = WORKING;
mRecognitionView.showWorking(mWaveBuffer, mSpeechStart, mWaveBuffer.size());
}
@Override
public void onError(int errorType) {
mState = ERROR;
VoiceInput.this.onError(errorType, mEndpointed);
}
@Override
public void onResults(Bundle resultsBundle) {
List<String> results = resultsBundle
.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
// VS Market update is needed for IME froyo clients to access the alternatesBundle
// TODO: verify this.
Bundle alternatesBundle = resultsBundle.getBundle(ALTERNATES_BUNDLE);
mState = DEFAULT;
final Map<String, List<CharSequence>> alternatives =
new HashMap<String, List<CharSequence>>();
if (ENABLE_WORD_CORRECTIONS && alternatesBundle != null && results.size() > 0) {
// Use the top recognition result to map each alternative's start:length to a word.
String[] words = results.get(0).split(" ");
Bundle spansBundle = alternatesBundle.getBundle(AlternatesBundleKeys.SPANS);
for (String key : spansBundle.keySet()) {
// Get the word for which these alternates correspond to.
Bundle spanBundle = spansBundle.getBundle(key);
int start = spanBundle.getInt(AlternatesBundleKeys.START);
int length = spanBundle.getInt(AlternatesBundleKeys.LENGTH);
// Only keep single-word based alternatives.
if (length == 1 && start < words.length) {
// Get the alternatives associated with the span.
// If a word appears twice in a recognition result,
// concatenate the alternatives for the word.
List<CharSequence> altList = alternatives.get(words[start]);
if (altList == null) {
altList = new ArrayList<CharSequence>();
alternatives.put(words[start], altList);
}
Parcelable[] alternatesArr = spanBundle
.getParcelableArray(AlternatesBundleKeys.ALTERNATES);
for (int j = 0; j < alternatesArr.length &&
altList.size() < MAX_ALT_LIST_LENGTH; j++) {
Bundle alternateBundle = (Bundle) alternatesArr[j];
String alternate = alternateBundle.getString(AlternatesBundleKeys.TEXT);
// Don't allow duplicates in the alternates list.
if (!altList.contains(alternate)) {
altList.add(alternate);
}
}
}
}
}
if (results.size() > 5) {
results = results.subList(0, 5);
}
mUiListener.onVoiceResults(results, alternatives);
mRecognitionView.finish();
}
@Override
public void onPartialResults(final Bundle partialResults) {
// currently - do nothing
}
@Override
public void onEvent(int eventType, Bundle params) {
// do nothing - reserved for events that might be added in the future
}
}
}

View File

@ -1,266 +0,0 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.voice;
import com.android.common.speech.LoggingEvents;
import com.android.inputmethod.deprecated.compat.VoiceInputLoggerCompatUtils;
import android.content.Context;
import android.content.Intent;
/**
* Provides the logging facility for voice input events. This fires broadcasts back to
* the voice search app which then logs on our behalf.
*
* Note that debug console logging does not occur in this class. If you want to
* see console output of these logging events, there is a boolean switch to turn
* on on the VoiceSearch side.
*/
public class VoiceInputLogger {
@SuppressWarnings("unused")
private static final String TAG = VoiceInputLogger.class.getSimpleName();
private static VoiceInputLogger sVoiceInputLogger;
private final Context mContext;
// The base intent used to form all broadcast intents to the logger
// in VoiceSearch.
private final Intent mBaseIntent;
// This flag is used to indicate when there are voice events that
// need to be flushed.
private boolean mHasLoggingInfo = false;
/**
* Returns the singleton of the logger.
*
* @param contextHint a hint context used when creating the logger instance.
* Ignored if the singleton instance already exists.
*/
public static synchronized VoiceInputLogger getLogger(Context contextHint) {
if (sVoiceInputLogger == null) {
sVoiceInputLogger = new VoiceInputLogger(contextHint);
}
return sVoiceInputLogger;
}
public VoiceInputLogger(Context context) {
mContext = context;
mBaseIntent = new Intent(LoggingEvents.ACTION_LOG_EVENT);
mBaseIntent.putExtra(LoggingEvents.EXTRA_APP_NAME, LoggingEvents.VoiceIme.APP_NAME);
}
private Intent newLoggingBroadcast(int event) {
Intent i = new Intent(mBaseIntent);
i.putExtra(LoggingEvents.EXTRA_EVENT, event);
return i;
}
public void flush() {
if (hasLoggingInfo()) {
Intent i = new Intent(mBaseIntent);
i.putExtra(LoggingEvents.EXTRA_FLUSH, true);
mContext.sendBroadcast(i);
setHasLoggingInfo(false);
}
}
public void keyboardWarningDialogShown() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_SHOWN));
}
public void keyboardWarningDialogDismissed() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_DISMISSED));
}
public void keyboardWarningDialogOk() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_OK));
}
public void keyboardWarningDialogCancel() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_CANCEL));
}
public void settingsWarningDialogShown() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_SHOWN));
}
public void settingsWarningDialogDismissed() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_DISMISSED));
}
public void settingsWarningDialogOk() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_OK));
}
public void settingsWarningDialogCancel() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_CANCEL));
}
public void swipeHintDisplayed() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.SWIPE_HINT_DISPLAYED));
}
public void cancelDuringListening() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_LISTENING));
}
public void cancelDuringWorking() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_WORKING));
}
public void cancelDuringError() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_ERROR));
}
public void punctuationHintDisplayed() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.PUNCTUATION_HINT_DISPLAYED));
}
public void error(int code) {
setHasLoggingInfo(true);
Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.ERROR);
i.putExtra(LoggingEvents.VoiceIme.EXTRA_ERROR_CODE, code);
mContext.sendBroadcast(i);
}
public void start(String locale, boolean swipe) {
setHasLoggingInfo(true);
Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.START);
i.putExtra(LoggingEvents.VoiceIme.EXTRA_START_LOCALE, locale);
i.putExtra(LoggingEvents.VoiceIme.EXTRA_START_SWIPE, swipe);
i.putExtra(LoggingEvents.EXTRA_TIMESTAMP, System.currentTimeMillis());
mContext.sendBroadcast(i);
}
public void voiceInputDelivered(int length) {
setHasLoggingInfo(true);
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) {
setHasLoggingInfo(true);
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) {
setHasLoggingInfo(true);
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) {
setHasLoggingInfo(true);
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 textModifiedByChooseSuggestion(int suggestionLength, int replacedPhraseLength,
int index, String before, String after) {
setHasLoggingInfo(true);
Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED);
i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, suggestionLength);
i.putExtra(VoiceInputLoggerCompatUtils.EXTRA_TEXT_REPLACED_LENGTH, replacedPhraseLength);
i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE,
LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_CHOOSE_SUGGESTION);
i.putExtra(LoggingEvents.VoiceIme.EXTRA_N_BEST_CHOOSE_INDEX, index);
i.putExtra(VoiceInputLoggerCompatUtils.EXTRA_BEFORE_N_BEST_CHOOSE, before);
i.putExtra(VoiceInputLoggerCompatUtils.EXTRA_AFTER_N_BEST_CHOOSE, after);
mContext.sendBroadcast(i);
}
public void inputEnded() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.INPUT_ENDED));
}
public void voiceInputSettingEnabled() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.VOICE_INPUT_SETTING_ENABLED));
}
public void voiceInputSettingDisabled() {
setHasLoggingInfo(true);
mContext.sendBroadcast(newLoggingBroadcast(
LoggingEvents.VoiceIme.VOICE_INPUT_SETTING_DISABLED));
}
private void setHasLoggingInfo(boolean hasLoggingInfo) {
mHasLoggingInfo = hasLoggingInfo;
// If applications that call UserHappinessSignals.userAcceptedImeText
// make that call after VoiceInputLogger.flush() calls this method with false, we
// will lose those happiness signals. For example, consider the gmail sequence:
// 1. compose message
// 2. speak message into message field
// 3. type subject into subject field
// 4. press send
// We will NOT get the signal that the user accepted the voice inputted message text
// because when the user tapped on the subject field, the ime's flush will be triggered
// and the hasLoggingInfo will be then set to false. So by the time the user hits send
// we have essentially forgotten about any voice input.
// However the following (more common) use case is properly logged
// 1. compose message
// 2. type subject in subject field
// 3. speak message in message field
// 4. press send
VoiceInputLoggerCompatUtils.setHasVoiceLoggingInfoCompat(hasLoggingInfo);
}
private boolean hasLoggingInfo(){
return mHasLoggingInfo;
}
}

View File

@ -1,92 +0,0 @@
/*
* Copyright (C) 2008-2009 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.voice;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
/**
* Utility class to draw a waveform into a bitmap, given a byte array
* that represents the waveform as a sequence of 16-bit integers.
* Adapted from RecognitionActivity.java.
*/
public class WaveformImage {
private static final int SAMPLING_RATE = 8000;
private WaveformImage() {
// Intentional empty constructor.
}
public static Bitmap drawWaveform(
ByteArrayOutputStream waveBuffer, int w, int h, int start, int end) {
final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(b);
final Paint paint = new Paint();
paint.setColor(0xFFFFFFFF); // 0xRRGGBBAA
paint.setAntiAlias(true);
paint.setStrokeWidth(0);
final ShortBuffer buf = ByteBuffer
.wrap(waveBuffer.toByteArray())
.order(ByteOrder.nativeOrder())
.asShortBuffer();
buf.position(0);
final int numSamples = waveBuffer.size() / 2;
final int delay = (SAMPLING_RATE * 100 / 1000);
int endIndex = end / 2 + delay;
if (end == 0 || endIndex >= numSamples) {
endIndex = numSamples;
}
int index = start / 2 - delay;
if (index < 0) {
index = 0;
}
final int size = endIndex - index;
int numSamplePerPixel = 32;
int delta = size / (numSamplePerPixel * w);
if (delta == 0) {
numSamplePerPixel = size / w;
delta = 1;
}
final float scale = 3.5f / 65536.0f;
// do one less column to make sure we won't read past
// the buffer.
try {
for (int i = 0; i < w - 1 ; i++) {
final float x = i;
for (int j = 0; j < numSamplePerPixel; j++) {
final short s = buf.get(index);
final float y = (h / 2) - (s * h * scale);
c.drawPoint(x, y, paint);
index += delta;
}
}
} catch (IndexOutOfBoundsException e) {
// this can happen, but we don't care
}
return b;
}
}

View File

@ -1,68 +0,0 @@
/*
* Copyright (C) 2009 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.deprecated.voice;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;
/**
* A set of text fields where speech has been explicitly enabled.
*/
public class Whitelist {
private List<Bundle> mConditions;
public Whitelist() {
mConditions = new ArrayList<Bundle>();
}
public Whitelist(List<Bundle> conditions) {
this.mConditions = conditions;
}
public void addApp(String app) {
Bundle bundle = new Bundle();
bundle.putString("packageName", app);
mConditions.add(bundle);
}
/**
* @return true if the field is a member of the whitelist.
*/
public boolean matches(FieldContext context) {
for (Bundle condition : mConditions) {
if (matches(condition, context.getBundle())) {
return true;
}
}
return false;
}
/**
* @return true of all values in condition are matched by a value
* in target.
*/
private boolean matches(Bundle condition, Bundle target) {
for (String key : condition.keySet()) {
if (!condition.getString(key).equals(target.getString(key))) {
return false;
}
}
return true;
}
}

View File

@ -390,30 +390,4 @@ public class KeyboardSet {
} }
} }
} }
// TODO: Should be removed. This is no longer required if {@link InputMethodSubtype} is
// supported.
public static String parseKeyboardLocale(Resources res, int resId)
throws XmlPullParserException, IOException {
final XmlPullParser parser = res.getXml(resId);
if (parser == null)
return "";
int event;
while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (event == XmlPullParser.START_TAG) {
final String tag = parser.getName();
if (TAG_KEYBOARD_SET.equals(tag)) {
final TypedArray keyboardSetAttr = res.obtainAttributes(
Xml.asAttributeSet(parser), R.styleable.KeyboardSet);
final String locale = keyboardSetAttr.getString(
R.styleable.KeyboardSet_keyboardLocale);
keyboardSetAttr.recycle();
return locale;
} else {
throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
}
}
}
return "";
}
} }

View File

@ -39,7 +39,6 @@ import android.widget.PopupWindow;
import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.keyboard.internal.KeySpecParser;
@ -828,12 +827,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
} }
} }
@Override
protected void onAttachedToWindow() {
// Token is available from here.
VoiceProxy.getInstance().onAttachedToWindow();
}
/** /**
* Receives hover events from the input framework. This method overrides * Receives hover events from the input framework. This method overrides
* View.dispatchHoverEvent(MotionEvent) on SDK version ICS or higher. On * View.dispatchHoverEvent(MotionEvent) on SDK version ICS or higher. On

View File

@ -60,8 +60,6 @@ import com.android.inputmethod.compat.InputMethodServiceCompatWrapper;
import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
import com.android.inputmethod.compat.InputTypeCompatUtils; import com.android.inputmethod.compat.InputTypeCompatUtils;
import com.android.inputmethod.compat.SuggestionSpanUtils; import com.android.inputmethod.compat.SuggestionSpanUtils;
import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardActionListener; import com.android.inputmethod.keyboard.KeyboardActionListener;
import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.KeyboardId;
@ -193,7 +191,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private SharedPreferences mPrefs; private SharedPreferences mPrefs;
/* package for tests */ final KeyboardSwitcher mKeyboardSwitcher; /* package for tests */ final KeyboardSwitcher mKeyboardSwitcher;
private final SubtypeSwitcher mSubtypeSwitcher; private final SubtypeSwitcher mSubtypeSwitcher;
private VoiceProxy mVoiceProxy;
private boolean mShouldSwitchToLastSubtype = true; private boolean mShouldSwitchToLastSubtype = true;
private UserDictionary mUserDictionary; private UserDictionary mUserDictionary;
@ -234,7 +231,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> {
private static final int MSG_UPDATE_SHIFT_STATE = 1; private static final int MSG_UPDATE_SHIFT_STATE = 1;
private static final int MSG_VOICE_RESULTS = 2;
private static final int MSG_SPACE_TYPED = 4; private static final int MSG_SPACE_TYPED = 4;
private static final int MSG_SET_BIGRAM_PREDICTIONS = 5; private static final int MSG_SET_BIGRAM_PREDICTIONS = 5;
private static final int MSG_PENDING_IMS_CALLBACK = 6; private static final int MSG_PENDING_IMS_CALLBACK = 6;
@ -272,11 +268,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
case MSG_SET_BIGRAM_PREDICTIONS: case MSG_SET_BIGRAM_PREDICTIONS:
latinIme.updateBigramPredictions(); latinIme.updateBigramPredictions();
break; break;
case MSG_VOICE_RESULTS:
final Keyboard keyboard = switcher.getKeyboard();
latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization()
|| (keyboard != null && keyboard.isShiftedOrShiftLocked()));
break;
} }
} }
@ -311,10 +302,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
removeMessages(MSG_SET_BIGRAM_PREDICTIONS); removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
} }
public void updateVoiceResults() {
sendMessage(obtainMessage(MSG_VOICE_RESULTS));
}
public void startDoubleSpacesTimer() { public void startDoubleSpacesTimer() {
removeMessages(MSG_SPACE_TYPED); removeMessages(MSG_SPACE_TYPED);
sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), mDoubleSpacesTurnIntoPeriodTimeout); sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), mDoubleSpacesTurnIntoPeriodTimeout);
@ -436,7 +423,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (ProductionFlag.IS_EXPERIMENTAL) { if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.init(this, prefs); ResearchLogger.init(this, prefs);
} }
LanguageSwitcherProxy.init(this, prefs);
InputMethodManagerCompatWrapper.init(this); InputMethodManagerCompatWrapper.init(this);
SubtypeSwitcher.init(this); SubtypeSwitcher.init(this);
KeyboardSwitcher.init(this, prefs); KeyboardSwitcher.init(this, prefs);
@ -476,7 +462,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
registerReceiver(mReceiver, filter); registerReceiver(mReceiver, filter);
mVoiceProxy = VoiceProxy.init(this, prefs, mHandler);
final IntentFilter packageFilter = new IntentFilter(); final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
@ -577,7 +562,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} }
unregisterReceiver(mReceiver); unregisterReceiver(mReceiver);
unregisterReceiver(mDictionaryPackInstallReceiver); unregisterReceiver(mDictionaryPackInstallReceiver);
mVoiceProxy.destroy();
LatinImeLogger.commit(); LatinImeLogger.commit();
LatinImeLogger.onDestroy(); LatinImeLogger.onDestroy();
super.onDestroy(); super.onDestroy();
@ -596,14 +580,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (isShowingOptionDialog()) if (isShowingOptionDialog())
mOptionsDialog.dismiss(); mOptionsDialog.dismiss();
} }
mVoiceProxy.startChangingConfiguration();
super.onConfigurationChanged(conf); super.onConfigurationChanged(conf);
mVoiceProxy.onConfigurationChanged(conf);
mVoiceProxy.finishChangingConfiguration();
// This will work only when the subtype is not supported.
LanguageSwitcherProxy.onConfigurationChanged(conf);
} }
@Override @Override
@ -698,13 +675,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mSubtypeSwitcher.updateParametersOnStartInputView(); mSubtypeSwitcher.updateParametersOnStartInputView();
// Most such things we decide below in initializeInputAttributesAndGetMode, but we need to
// know now whether this is a password text field, because we need to know now whether we
// want to enable the voice button.
final int inputType = editorInfo.inputType;
mVoiceProxy.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType)
|| InputTypeCompatUtils.isVisiblePasswordInputType(inputType));
// The EditorInfo might have a flag that affects fullscreen mode. // The EditorInfo might have a flag that affects fullscreen mode.
// Note: This call should be done by InputMethodService? // Note: This call should be done by InputMethodService?
updateFullscreenMode(); updateFullscreenMode();
@ -726,9 +696,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) { if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) {
mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold);
} }
mVoiceProxy.loadSettings(editorInfo, mPrefs);
// This will work only when the subtype is not supported.
LanguageSwitcherProxy.loadSettings();
if (mSubtypeSwitcher.isKeyboardMode()) { if (mSubtypeSwitcher.isKeyboardMode()) {
switcher.loadKeyboard(editorInfo, mSettingsValues); switcher.loadKeyboard(editorInfo, mSettingsValues);
@ -746,8 +713,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mSettingsValues.mKeyPreviewPopupDismissDelay); mSettingsValues.mKeyPreviewPopupDismissDelay);
inputView.setProximityCorrectionEnabled(true); inputView.setProximityCorrectionEnabled(true);
mVoiceProxy.onStartInputView(inputView.getWindowToken());
if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
} }
@ -763,8 +728,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
LatinImeLogger.commit(); LatinImeLogger.commit();
mVoiceProxy.flushVoiceInputLogs();
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) inputView.closing(); if (inputView != null) inputView.closing();
if (mUserHistoryDictionary != null) mUserHistoryDictionary.flushPendingWrites(); if (mUserHistoryDictionary != null) mUserHistoryDictionary.flushPendingWrites();
@ -779,12 +742,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mHandler.cancelUpdateSuggestions(); mHandler.cancelUpdateSuggestions();
} }
@Override
public void onUpdateExtractedText(int token, ExtractedText text) {
super.onUpdateExtractedText(token, text);
mVoiceProxy.showPunctuationHintIfNecessary();
}
@Override @Override
public void onUpdateSelection(int oldSelStart, int oldSelEnd, public void onUpdateSelection(int oldSelStart, int oldSelEnd,
int newSelStart, int newSelEnd, int newSelStart, int newSelEnd,
@ -816,8 +773,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
+ ", ce=" + composingSpanEnd); + ", ce=" + composingSpanEnd);
} }
mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart);
// TODO: refactor the following code to be less contrived. // TODO: refactor the following code to be less contrived.
// "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means
// that the cursor is not at the end of the composing span, or there is a selection. // that the cursor is not at the end of the composing span, or there is a selection.
@ -905,7 +860,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mOptionsDialog.dismiss(); mOptionsDialog.dismiss();
mOptionsDialog = null; mOptionsDialog = null;
} }
mVoiceProxy.hideVoiceWindow();
super.hideWindow(); super.hideWindow();
} }
@ -1094,7 +1048,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (ic != null) { if (ic != null) {
ic.finishComposingText(); ic.finishComposingText();
} }
mVoiceProxy.setVoiceInputHighlighted(false);
} }
private void resetComposingState(final boolean alsoResetLastComposedWord) { private void resetComposingState(final boolean alsoResetLastComposedWord) {
@ -1184,14 +1137,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private void onSettingsKeyPressed() { private void onSettingsKeyPressed() {
if (isShowingOptionDialog()) return; if (isShowingOptionDialog()) return;
if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
showSubtypeSelectorAndSettings(); showSubtypeSelectorAndSettings();
} else if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(
false /* exclude aux subtypes */)) {
showOptionsMenu();
} else {
launchSettings();
}
} }
// Virtual codes representing custom requests. These are used in onCustomRequest() below. // Virtual codes representing custom requests. These are used in onCustomRequest() below.
@ -1351,7 +1297,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override @Override
public void onTextInput(CharSequence text) { public void onTextInput(CharSequence text) {
mVoiceProxy.commitVoiceInput();
final InputConnection ic = getCurrentInputConnection(); final InputConnection ic = getCurrentInputConnection();
if (ic == null) return; if (ic == null) return;
ic.beginBatchEdit(); ic.beginBatchEdit();
@ -1396,7 +1341,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} }
private void handleBackspace(final int spaceState) { private void handleBackspace(final int spaceState) {
if (mVoiceProxy.logAndRevertVoiceInput()) return;
final InputConnection ic = getCurrentInputConnection(); final InputConnection ic = getCurrentInputConnection();
if (ic == null) return; if (ic == null) return;
ic.beginBatchEdit(); ic.beginBatchEdit();
@ -1406,8 +1350,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// "ic" may not be null. // "ic" may not be null.
private void handleBackspaceWhileInBatchEdit(final int spaceState, final InputConnection ic) { private void handleBackspaceWhileInBatchEdit(final int spaceState, final InputConnection ic) {
mVoiceProxy.handleBackspace();
// In many cases, we may have to put the keyboard in auto-shift state again. // In many cases, we may have to put the keyboard in auto-shift state again.
mHandler.postUpdateShiftState(); mHandler.postUpdateShiftState();
@ -1506,7 +1448,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private void handleCharacter(final int primaryCode, final int x, private void handleCharacter(final int primaryCode, final int x,
final int y, final int spaceState) { final int y, final int spaceState) {
mVoiceProxy.handleCharacter();
final InputConnection ic = getCurrentInputConnection(); final InputConnection ic = getCurrentInputConnection();
if (null != ic) ic.beginBatchEdit(); if (null != ic) ic.beginBatchEdit();
// TODO: if ic is null, does it make any sense to call this? // TODO: if ic is null, does it make any sense to call this?
@ -1582,8 +1523,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Returns true if we did an autocorrection, false otherwise. // Returns true if we did an autocorrection, false otherwise.
private boolean handleSeparator(final int primaryCode, final int x, final int y, private boolean handleSeparator(final int primaryCode, final int x, final int y,
final int spaceState) { final int spaceState) {
mVoiceProxy.handleSeparator();
// Should dismiss the "Touch again to save" message when handling separator // Should dismiss the "Touch again to save" message when handling separator
if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) {
mHandler.cancelUpdateBigramPredictions(); mHandler.cancelUpdateBigramPredictions();
@ -1669,7 +1608,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private void handleClose() { private void handleClose() {
commitTyped(getCurrentInputConnection(), LastComposedWord.NOT_A_SEPARATOR); commitTyped(getCurrentInputConnection(), LastComposedWord.NOT_A_SEPARATOR);
mVoiceProxy.handleClose();
requestHideSelf(0); requestHideSelf(0);
LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) if (inputView != null)
@ -1749,8 +1687,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public void updateSuggestions() { public void updateSuggestions() {
// Check if we have a suggestion engine attached. // Check if we have a suggestion engine attached.
if ((mSuggest == null || !isSuggestionsRequested()) if ((mSuggest == null || !isSuggestionsRequested())) {
&& !mVoiceProxy.isVoiceInputHighlighted()) {
if (mWordComposer.isComposingWord()) { if (mWordComposer.isComposingWord()) {
Log.w(TAG, "Called updateSuggestions but suggestions were not requested!"); Log.w(TAG, "Called updateSuggestions but suggestions were not requested!");
mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
@ -1859,8 +1796,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override @Override
public void pickSuggestionManually(final int index, final CharSequence suggestion) { public void pickSuggestionManually(final int index, final CharSequence suggestion) {
final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion,
mSettingsValues.mWordSeparators);
if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) { if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) {
int firstChar = Character.codePointAt(suggestion, 0); int firstChar = Character.codePointAt(suggestion, 0);
@ -1953,7 +1888,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final int separatorCode) { final int separatorCode) {
final InputConnection ic = getCurrentInputConnection(); final InputConnection ic = getCurrentInputConnection();
if (ic != null) { if (ic != null) {
mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators);
if (mSettingsValues.mEnableSuggestionSpanInsertion) { if (mSettingsValues.mEnableSuggestionSpanInsertion) {
final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
@ -2206,11 +2140,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Notify that language or mode have been changed and toggleLanguage will update KeyboardID // Notify that language or mode have been changed and toggleLanguage will update KeyboardID
// according to new language or mode. // according to new language or mode.
public void onRefreshKeyboard() { public void onRefreshKeyboard() {
if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
// Before Honeycomb, Voice IME is in LatinIME and it changes the current input view,
// so that we need to re-create the keyboard input view here.
setInputView(mKeyboardSwitcher.onCreateInputView());
}
// When the device locale is changed in SetupWizard etc., this method may get called via // When the device locale is changed in SetupWizard etc., this method may get called via
// onConfigurationChanged before SoftInputWindow is shown. // onConfigurationChanged before SoftInputWindow is shown.
if (mKeyboardSwitcher.getKeyboardView() != null) { if (mKeyboardSwitcher.getKeyboardView() != null) {
@ -2269,11 +2198,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} }
}; };
// TODO: remove this method when VoiceProxy has been removed
public void vibrate() {
mFeedbackManager.vibrate(mKeyboardSwitcher.getKeyboardView());
}
private void updateCorrectionMode() { private void updateCorrectionMode() {
// TODO: cleanup messy flags // TODO: cleanup messy flags
final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled
@ -2341,32 +2265,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
showOptionDialogInternal(builder.create()); showOptionDialogInternal(builder.create());
} }
private void showOptionsMenu() {
final CharSequence title = getString(R.string.english_ime_input_options);
final CharSequence[] items = new CharSequence[] {
getString(R.string.selectInputMethod),
getString(R.string.english_ime_settings),
};
final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface di, int position) {
di.dismiss();
switch (position) {
case 0:
mImm.showInputMethodPicker();
break;
case 1:
launchSettings();
break;
}
}
};
final AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setItems(items, listener)
.setTitle(title);
showOptionDialogInternal(builder.create());
}
@Override @Override
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
super.dump(fd, fout, args); super.dump(fd, fout, args);

View File

@ -45,15 +45,13 @@ import android.widget.TextView;
import com.android.inputmethod.compat.CompatUtils; import com.android.inputmethod.compat.CompatUtils;
import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; import com.android.inputmethod.compat.InputMethodServiceCompatWrapper;
import com.android.inputmethod.compat.VibratorCompatWrapper; import com.android.inputmethod.compat.VibratorCompatWrapper;
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethodcommon.InputMethodSettingsActivity; import com.android.inputmethodcommon.InputMethodSettingsActivity;
import java.util.Locale; import java.util.Locale;
public class Settings extends InputMethodSettingsActivity public class Settings extends InputMethodSettingsActivity
implements SharedPreferences.OnSharedPreferenceChangeListener, implements SharedPreferences.OnSharedPreferenceChangeListener, OnPreferenceClickListener {
DialogInterface.OnDismissListener, OnPreferenceClickListener {
private static final String TAG = Settings.class.getSimpleName(); private static final String TAG = Settings.class.getSimpleName();
public static final boolean ENABLE_EXPERIMENTAL_SETTINGS = false; public static final boolean ENABLE_EXPERIMENTAL_SETTINGS = false;
@ -92,9 +90,6 @@ public class Settings extends InputMethodSettingsActivity
public static final String PREF_SELECTED_LANGUAGES = "selected_languages"; public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
public static final String PREF_DEBUG_SETTINGS = "debug_settings"; public static final String PREF_DEBUG_SETTINGS = "debug_settings";
// Dialog ids
private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
private PreferenceScreen mInputLanguageSelection; private PreferenceScreen mInputLanguageSelection;
private PreferenceScreen mKeypressVibrationDurationSettingsPref; private PreferenceScreen mKeypressVibrationDurationSettingsPref;
private PreferenceScreen mKeypressSoundVolumeSettingsPref; private PreferenceScreen mKeypressSoundVolumeSettingsPref;
@ -113,7 +108,6 @@ public class Settings extends InputMethodSettingsActivity
private TextView mKeypressVibrationDurationSettingsTextView; private TextView mKeypressVibrationDurationSettingsTextView;
private TextView mKeypressSoundVolumeSettingsTextView; private TextView mKeypressSoundVolumeSettingsTextView;
private boolean mOkClicked = false;
private String mVoiceModeOff; private String mVoiceModeOff;
private void ensureConsistencyOfAutoCorrectionSettings() { private void ensureConsistencyOfAutoCorrectionSettings() {
@ -291,9 +285,7 @@ public class Settings extends InputMethodSettingsActivity
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled(); final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
if (isShortcutImeEnabled if (isShortcutImeEnabled) {
|| (VoiceProxy.VOICE_INSTALLED
&& VoiceProxy.isRecognitionAvailable(getActivityInternal()))) {
updateVoiceModeSummary(); updateVoiceModeSummary();
} else { } else {
getPreferenceScreen().removePreference(mVoicePreference); getPreferenceScreen().removePreference(mVoicePreference);
@ -312,13 +304,7 @@ public class Settings extends InputMethodSettingsActivity
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
(new BackupManager(getActivityInternal())).dataChanged(); (new BackupManager(getActivityInternal())).dataChanged();
// If turning on voice input, show dialog if (key.equals(PREF_POPUP_ON)) {
if (key.equals(PREF_VOICE_MODE) && !mVoiceOn) {
if (!prefs.getString(PREF_VOICE_MODE, mVoiceModeOff)
.equals(mVoiceModeOff)) {
showVoiceConfirmation();
}
} else if (key.equals(PREF_POPUP_ON)) {
final ListPreference popupDismissDelay = final ListPreference popupDismissDelay =
(ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); (ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
if (null != popupDismissDelay) { if (null != popupDismissDelay) {
@ -363,80 +349,12 @@ public class Settings extends InputMethodSettingsActivity
lp.setSummary(lp.getEntries()[lp.findIndexOfValue(lp.getValue())]); lp.setSummary(lp.getEntries()[lp.findIndexOfValue(lp.getValue())]);
} }
private void showVoiceConfirmation() {
mOkClicked = false;
getActivityInternal().showDialog(VOICE_INPUT_CONFIRM_DIALOG);
// Make URL in the dialog message clickable
if (mDialog != null) {
TextView textView = (TextView) mDialog.findViewById(android.R.id.message);
if (textView != null) {
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
}
}
private void updateVoiceModeSummary() { private void updateVoiceModeSummary() {
mVoicePreference.setSummary( mVoicePreference.setSummary(
getResources().getStringArray(R.array.voice_input_modes_summary) getResources().getStringArray(R.array.voice_input_modes_summary)
[mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]); [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
} }
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case VOICE_INPUT_CONFIRM_DIALOG:
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
mVoicePreference.setValue(mVoiceModeOff);
} else if (whichButton == DialogInterface.BUTTON_POSITIVE) {
mOkClicked = true;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(getActivityInternal())
.setTitle(R.string.voice_warning_title)
.setPositiveButton(android.R.string.ok, listener)
.setNegativeButton(android.R.string.cancel, listener);
// Get the current list of supported locales and check the current locale against
// that list, to decide whether to put a warning that voice input will not work in
// the current language as part of the pop-up confirmation dialog.
boolean localeSupported = SubtypeSwitcher.isVoiceSupported(
this, Locale.getDefault().toString());
final CharSequence message;
if (localeSupported) {
message = TextUtils.concat(
getText(R.string.voice_warning_may_not_understand), "\n\n",
getText(R.string.voice_hint_dialog_message));
} else {
message = TextUtils.concat(
getText(R.string.voice_warning_locale_not_supported), "\n\n",
getText(R.string.voice_warning_may_not_understand), "\n\n",
getText(R.string.voice_hint_dialog_message));
}
builder.setMessage(message);
AlertDialog dialog = builder.create();
mDialog = dialog;
dialog.setOnDismissListener(this);
return dialog;
default:
Log.e(TAG, "unknown dialog " + id);
return null;
}
}
@Override
public void onDismiss(DialogInterface dialog) {
if (!mOkClicked) {
// This assumes that onPreferenceClick gets called first, and this if the user
// agreed after the warning, we set the mOkClicked value to true.
mVoicePreference.setValue(mVoiceModeOff);
}
}
private void refreshEnablingsOfKeypressSoundAndVibrationSettings( private void refreshEnablingsOfKeypressSoundAndVibrationSettings(
SharedPreferences sp, Resources res) { SharedPreferences sp, Resources res) {
if (mKeypressVibrationDurationSettingsPref != null) { if (mKeypressVibrationDurationSettingsPref != null) {

View File

@ -33,7 +33,6 @@ import android.util.Log;
import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; import com.android.inputmethod.compat.InputMethodInfoCompatWrapper;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardSwitcher;
import java.util.ArrayList; import java.util.ArrayList;
@ -76,7 +75,6 @@ public class SubtypeSwitcher {
private Locale mSystemLocale; private Locale mSystemLocale;
private Locale mInputLocale; private Locale mInputLocale;
private String mInputLocaleStr; private String mInputLocaleStr;
private VoiceProxy.VoiceInputWrapper mVoiceInputWrapper;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
private boolean mIsNetworkConnected; private boolean mIsNetworkConnected;
@ -108,7 +106,6 @@ public class SubtypeSwitcher {
mInputLocaleStr = null; mInputLocaleStr = null;
mCurrentSubtype = null; mCurrentSubtype = null;
mAllEnabledSubtypesOfCurrentInputMethod = null; mAllEnabledSubtypesOfCurrentInputMethod = null;
mVoiceInputWrapper = null;
final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
mIsNetworkConnected = (info != null && info.isConnected()); mIsNetworkConnected = (info != null && info.isConnected());
@ -234,34 +231,12 @@ public class SubtypeSwitcher {
} }
mCurrentSubtype = newSubtype; mCurrentSubtype = newSubtype;
// If the old mode is voice input, we need to reset or cancel its status.
// We cancel its status when we change mode, while we reset otherwise.
if (isKeyboardMode()) { if (isKeyboardMode()) {
if (modeChanged) {
if (VOICE_MODE.equals(oldMode) && mVoiceInputWrapper != null) {
mVoiceInputWrapper.cancel();
}
}
if (modeChanged || languageChanged) { if (modeChanged || languageChanged) {
updateShortcutIME(); updateShortcutIME();
mService.onRefreshKeyboard(); mService.onRefreshKeyboard();
} }
} else if (isVoiceMode() && mVoiceInputWrapper != null) {
if (VOICE_MODE.equals(oldMode)) {
mVoiceInputWrapper.reset();
}
// If needsToShowWarningDialog is true, voice input need to show warning before
// show recognition view.
if (languageChanged || modeChanged
|| VoiceProxy.getInstance().needsToShowWarningDialog()) {
triggerVoiceIME();
}
} else { } else {
if (VOICE_MODE.equals(oldMode) && mVoiceInputWrapper != null) {
// We need to reset the voice input to release the resources and to reset its status
// as it is not the current input mode.
mVoiceInputWrapper.reset();
}
final String packageName = mService.getPackageName(); final String packageName = mService.getPackageName();
int version = -1; int version = -1;
try { try {
@ -270,7 +245,7 @@ public class SubtypeSwitcher {
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {
} }
Log.w(TAG, "Unknown subtype mode: " + newMode + "," + version + ", " + packageName Log.w(TAG, "Unknown subtype mode: " + newMode + "," + version + ", " + packageName
+ ", " + mVoiceInputWrapper + ". IME is already changed to other IME."); + ". IME is already changed to other IME.");
if (newSubtype != null) { if (newSubtype != null) {
Log.w(TAG, "Subtype mode:" + newSubtype.getMode()); Log.w(TAG, "Subtype mode:" + newSubtype.getMode());
Log.w(TAG, "Subtype locale:" + newSubtype.getLocale()); Log.w(TAG, "Subtype locale:" + newSubtype.getLocale());
@ -477,40 +452,6 @@ public class SubtypeSwitcher {
return KEYBOARD_MODE.equals(getCurrentSubtypeMode()); return KEYBOARD_MODE.equals(getCurrentSubtypeMode());
} }
///////////////////////////
// Voice Input functions //
///////////////////////////
public boolean setVoiceInputWrapper(VoiceProxy.VoiceInputWrapper vi) {
if (mVoiceInputWrapper == null && vi != null) {
mVoiceInputWrapper = vi;
if (isVoiceMode()) {
if (DBG) {
Log.d(TAG, "Set and call voice input.: " + getInputLocaleStr());
}
triggerVoiceIME();
return true;
}
}
return false;
}
public boolean isVoiceMode() {
return null == mCurrentSubtype ? false : VOICE_MODE.equals(getCurrentSubtypeMode());
}
public boolean isDummyVoiceMode() {
return mCurrentSubtype != null && mCurrentSubtype.getOriginalObject() == null
&& VOICE_MODE.equals(getCurrentSubtypeMode());
}
private void triggerVoiceIME() {
if (!mService.isInputViewShown()) return;
VoiceProxy.getInstance().startListening(false,
KeyboardSwitcher.getInstance().getKeyboardView().getWindowToken());
}
public String getInputLanguageName() { public String getInputLanguageName() {
return StringUtils.getDisplayLanguage(getInputLocale()); return StringUtils.getDisplayLanguage(getInputLocale());
} }
@ -537,18 +478,4 @@ public class SubtypeSwitcher {
public String getCurrentSubtypeMode() { public String getCurrentSubtypeMode() {
return null != mCurrentSubtype ? mCurrentSubtype.getMode() : KEYBOARD_MODE; return null != mCurrentSubtype ? mCurrentSubtype.getMode() : KEYBOARD_MODE;
} }
public static boolean isVoiceSupported(Context context, String locale) {
// Get the current list of supported locales and check the current locale against that
// list. We cache this value so as not to check it every time the user starts a voice
// input. Because this method is called by onStartInputView, this should mean that as
// long as the locale doesn't change while the user is keeping the IME open, the
// value should never be stale.
String supportedLocalesString = VoiceProxy.getSupportedLocalesString(
context.getContentResolver());
List<String> voiceInputSupportedLocales = Arrays.asList(
supportedLocalesString.split("\\s+"));
return voiceInputSupportedLocales.contains(locale);
}
} }