aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
authorsatok <satok@google.com>2011-03-28 18:45:49 -0700
committersatok <satok@google.com>2011-04-01 16:12:06 +0900
commit742900983830386f04ccb004cd4356c8b08c61d0 (patch)
tree377d3269ee86d6f65efbda7af8b04e2bbaffe6cf /java/src
parenta1f9cdd6f5328224e926335f2beeb27b1bc166fe (diff)
downloadlatinime-742900983830386f04ccb004cd4356c8b08c61d0.tar.gz
latinime-742900983830386f04ccb004cd4356c8b08c61d0.tar.xz
latinime-742900983830386f04ccb004cd4356c8b08c61d0.zip
Enable VoiceInput even if there is no shortcut subtype supported
Change-Id: I1d455348f56d73ecb942f22c2bbd03f240b489a6
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java85
-rw-r--r--java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java53
-rw-r--r--java/src/com/android/inputmethod/deprecated/VoiceProxy.java12
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java1
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java7
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java18
6 files changed, 165 insertions, 11 deletions
diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
index 5e66bf4d9..80586b753 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
@@ -16,8 +16,13 @@
package com.android.inputmethod.compat;
+import com.android.inputmethod.latin.LatinIME;
+import com.android.inputmethod.latin.SubtypeSwitcher;
+import com.android.inputmethod.latin.Utils;
+
import android.content.Context;
import android.os.IBinder;
+import android.text.TextUtils;
import android.util.Log;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -27,6 +32,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
// TODO: Override this class with the concrete implementation if we need to take care of the
@@ -50,7 +56,15 @@ public class InputMethodManagerCompatWrapper {
private static final InputMethodManagerCompatWrapper sInstance =
new InputMethodManagerCompatWrapper();
+ // 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.
+ private static final boolean ALLOW_DUMMY_SUBTYPE = true;
+ private static final boolean HAS_VOICE_FUNCTION = true;
+ private static final String VOICE_MODE = "voice";
+ private static final String KEYBOARD_MODE = "keyboard";
+
private InputMethodManager mImm;
+ private String mLatinImePackageName;
private InputMethodManagerCompatWrapper() {
}
@@ -64,28 +78,82 @@ public class InputMethodManagerCompatWrapper {
private synchronized void init(Context context) {
mImm = (InputMethodManager) context.getSystemService(
Context.INPUT_METHOD_SERVICE);
+ if (context instanceof LatinIME) {
+ mLatinImePackageName = context.getPackageName();
+ }
}
public InputMethodSubtypeCompatWrapper getCurrentInputMethodSubtype() {
- return new InputMethodSubtypeCompatWrapper(
- CompatUtils.invoke(mImm, null, METHOD_getCurrentInputMethodSubtype));
+ Object o = CompatUtils.invoke(mImm, null, METHOD_getCurrentInputMethodSubtype);
+ return new InputMethodSubtypeCompatWrapper(o);
}
public List<InputMethodSubtypeCompatWrapper> getEnabledInputMethodSubtypeList(
InputMethodInfoCompatWrapper imi, boolean allowsImplicitlySelectedSubtypes) {
Object retval = CompatUtils.invoke(mImm, null, METHOD_getEnabledInputMethodSubtypeList,
(imi != null ? imi.getInputMethodInfo() : null), allowsImplicitlySelectedSubtypes);
- // Returns an empty list
- if (retval == null)
- return Collections.emptyList();
+ if (retval == null || !(retval instanceof List) || ((List<?>)retval).isEmpty()) {
+ if (!ALLOW_DUMMY_SUBTYPE) {
+ // Returns an empty list
+ return Collections.emptyList();
+ }
+ // Creates dummy subtypes
+ List<InputMethodSubtypeCompatWrapper> subtypeList =
+ new ArrayList<InputMethodSubtypeCompatWrapper>();
+ InputMethodSubtypeCompatWrapper keyboardSubtype = getLastResortSubtype(KEYBOARD_MODE);
+ InputMethodSubtypeCompatWrapper voiceSubtype = getLastResortSubtype(VOICE_MODE);
+ if (keyboardSubtype != null) {
+ subtypeList.add(keyboardSubtype);
+ }
+ if (voiceSubtype != null) {
+ subtypeList.add(voiceSubtype);
+ }
+ return subtypeList;
+ }
return CompatUtils.copyInputMethodSubtypeListToWrapper((List<?>)retval);
}
+ private InputMethodInfoCompatWrapper getLatinImeInputMethodInfo() {
+ if (TextUtils.isEmpty(mLatinImePackageName))
+ return null;
+ return Utils.getInputMethodInfo(this, mLatinImePackageName);
+ }
+
+ @SuppressWarnings("unused")
+ private InputMethodSubtypeCompatWrapper getLastResortSubtype(String mode) {
+ if (VOICE_MODE.equals(mode) && !HAS_VOICE_FUNCTION)
+ return null;
+ Locale inputLocale = SubtypeSwitcher.getInstance().getInputLocale();
+ if (inputLocale == null)
+ return null;
+ return new InputMethodSubtypeCompatWrapper(0, 0, inputLocale.toString(), mode, "");
+ }
+
public Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>>
getShortcutInputMethodsAndSubtypes() {
Object retval = CompatUtils.invoke(mImm, null, METHOD_getShortcutInputMethodsAndSubtypes);
- // Returns an empty map
- if (!(retval instanceof Map)) return Collections.emptyMap();
+ if (retval == null || !(retval instanceof Map) || ((Map<?, ?>)retval).isEmpty()) {
+ if (!ALLOW_DUMMY_SUBTYPE) {
+ // Returns an empty map
+ return Collections.emptyMap();
+ }
+ // Creates dummy subtypes
+ InputMethodInfoCompatWrapper imi = getLatinImeInputMethodInfo();
+ InputMethodSubtypeCompatWrapper voiceSubtype = getLastResortSubtype(VOICE_MODE);
+ if (imi != null && voiceSubtype != null) {
+ Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>>
+ shortcutMap =
+ new HashMap<InputMethodInfoCompatWrapper,
+ List<InputMethodSubtypeCompatWrapper>>();
+ List<InputMethodSubtypeCompatWrapper> subtypeList =
+ new ArrayList<InputMethodSubtypeCompatWrapper>();
+ subtypeList.add(voiceSubtype);
+ shortcutMap.put(imi, subtypeList);
+ return shortcutMap;
+ } else {
+ return Collections.emptyMap();
+ }
+ }
Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>> shortcutMap =
new HashMap<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>>();
final Map<?, ?> retvalMap = (Map<?, ?>)retval;
@@ -107,6 +175,9 @@ public class InputMethodManagerCompatWrapper {
}
public boolean switchToLastInputMethod(IBinder token) {
+ if (SubtypeSwitcher.getInstance().isDummyVoiceMode()) {
+ return true;
+ }
return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToLastInputMethod, token);
}
diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java
index 3ffa81932..317b02216 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java
@@ -22,6 +22,7 @@ import android.text.TextUtils;
import android.util.Log;
import java.lang.reflect.Method;
+import java.util.Arrays;
// TODO: Override this class with the concrete implementation if we need to take care of the
// performance.
@@ -48,35 +49,65 @@ public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper
private static final Method METHOD_getExtraValueOf =
CompatUtils.getMethod(CLASS_InputMethodSubtype, "getExtraValueOf", String.class);
+ private final int mDummyNameResId;
+ private final int mDummyIconResId;
+ private final String mDummyLocale;
+ private final String mDummyMode;
+ private final String mDummyExtraValues;
+
public InputMethodSubtypeCompatWrapper(Object subtype) {
super((CLASS_InputMethodSubtype != null && CLASS_InputMethodSubtype.isInstance(subtype))
? subtype : null);
if (DBG) {
Log.d(TAG, "CreateInputMethodSubtypeCompatWrapper");
}
+ mDummyNameResId = 0;
+ mDummyIconResId = 0;
+ mDummyLocale = DEFAULT_LOCALE;
+ mDummyMode = DEFAULT_MODE;
+ mDummyExtraValues = "";
+ }
+
+ // Constructor for creating a dummy subtype.
+ public InputMethodSubtypeCompatWrapper(int nameResId, int iconResId, String locale,
+ String mode, String extraValues) {
+ super(null);
+ if (DBG) {
+ Log.d(TAG, "CreateInputMethodSubtypeCompatWrapper");
+ }
+ mDummyNameResId = nameResId;
+ mDummyIconResId = iconResId;
+ mDummyLocale = locale != null ? locale : "";
+ mDummyMode = mode != null ? mode : "";
+ mDummyExtraValues = extraValues != null ? extraValues : "";
}
public int getNameResId() {
+ if (mObj == null) return mDummyNameResId;
return (Integer)CompatUtils.invoke(mObj, 0, METHOD_getNameResId);
}
public int getIconResId() {
+ if (mObj == null) return mDummyIconResId;
return (Integer)CompatUtils.invoke(mObj, 0, METHOD_getIconResId);
}
public String getLocale() {
+ if (mObj == null) return mDummyLocale;
final String s = (String)CompatUtils.invoke(mObj, null, METHOD_getLocale);
if (TextUtils.isEmpty(s)) return DEFAULT_LOCALE;
return s;
}
public String getMode() {
+ if (mObj == null) return mDummyMode;
String s = (String)CompatUtils.invoke(mObj, null, METHOD_getMode);
if (TextUtils.isEmpty(s)) return DEFAULT_MODE;
return s;
}
public String getExtraValue() {
+ if (mObj == null) return mDummyExtraValues;
return (String)CompatUtils.invoke(mObj, null, METHOD_getExtraValue);
}
@@ -92,10 +123,32 @@ public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper
public boolean equals(Object o) {
if (o instanceof InputMethodSubtypeCompatWrapper) {
InputMethodSubtypeCompatWrapper subtype = (InputMethodSubtypeCompatWrapper)o;
+ if (mObj == null) {
+ // easy check of dummy subtypes
+ return (mDummyNameResId == subtype.mDummyNameResId
+ && mDummyIconResId == subtype.mDummyIconResId
+ && mDummyLocale.equals(subtype.mDummyLocale)
+ && mDummyMode.equals(subtype.mDummyMode)
+ && mDummyExtraValues.equals(subtype.mDummyExtraValues));
+ }
return mObj.equals(subtype.getOriginalObject());
} else {
return mObj.equals(o);
}
}
+ @Override
+ public int hashCode() {
+ if (mObj == null) {
+ return hashCodeInternal(mDummyNameResId, mDummyIconResId, mDummyLocale,
+ mDummyMode, mDummyExtraValues);
+ }
+ return mObj.hashCode();
+ }
+
+ private static int hashCodeInternal(int nameResId, int iconResId, String locale,
+ String mode, String extraValue) {
+ return Arrays
+ .hashCode(new Object[] { nameResId, iconResId, locale, mode, extraValue });
+ }
}
diff --git a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
index 5fba29d90..0d0591bd0 100644
--- a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
+++ b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
@@ -82,6 +82,8 @@ public class VoiceProxy implements VoiceInput.UiListener {
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;
@@ -99,6 +101,7 @@ public class VoiceProxy implements VoiceInput.UiListener {
private boolean mVoiceButtonOnPrimary;
private boolean mVoiceInputHighlighted;
+ private int mMinimumVoiceRecognitionViewHeightPixel;
private InputMethodManagerCompatWrapper mImm;
private LatinIME mService;
private AlertDialog mVoiceWarningDialog;
@@ -107,6 +110,7 @@ public class VoiceProxy implements VoiceInput.UiListener {
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>>();
@@ -123,6 +127,8 @@ public class VoiceProxy implements VoiceInput.UiListener {
private void initInternal(LatinIME service, SharedPreferences prefs, UIHandler h) {
mService = service;
mHandler = h;
+ mMinimumVoiceRecognitionViewHeightPixel = Utils.dipToPixel(
+ Utils.getDipScale(service), RECOGNITIONVIEW_MINIMUM_HEIGHT_DIP);
mImm = InputMethodManagerCompatWrapper.getInstance(service);
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
if (VOICE_INSTALLED) {
@@ -542,7 +548,11 @@ public class VoiceProxy implements VoiceInput.UiListener {
mService.getResources().getDisplayMetrics().heightPixels;
final int currentHeight = popupLayout.getLayoutParams().height;
final int keyboardHeight = keyboardView.getHeight();
- if (keyboardHeight > currentHeight || keyboardHeight
+ if (mMinimumVoiceRecognitionViewHeightPixel > keyboardHeight
+ || mMinimumVoiceRecognitionViewHeightPixel > currentHeight) {
+ popupLayout.getLayoutParams().height =
+ mMinimumVoiceRecognitionViewHeightPixel;
+ } else if (keyboardHeight > currentHeight || keyboardHeight
> (displayHeight / RECOGNITIONVIEW_HEIGHT_THRESHOLD_RATIO)) {
popupLayout.getLayoutParams().height = keyboardHeight;
}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java b/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java
index 52c73ce90..b57c16f40 100644
--- a/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java
+++ b/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java
@@ -50,7 +50,6 @@ import java.util.Locale;
* plays beeps, shows errors, etc.
*/
public class RecognitionView {
- @SuppressWarnings("unused")
private static final String TAG = "RecognitionView";
private Handler mUiHandler; // Reference to UI thread
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 10a3369ac..053e2abe4 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -210,7 +210,7 @@ public class SubtypeSwitcher {
final String newLocale;
final String newMode;
final String oldMode = getCurrentSubtypeMode();
- if (newSubtype == null || !newSubtype.hasOriginalObject()) {
+ if (newSubtype == null) {
// Normally, newSubtype shouldn't be null. But just in case newSubtype was null,
// fallback to the default locale.
Log.w(TAG, "Couldn't get the current subtype.");
@@ -539,6 +539,11 @@ public class SubtypeSwitcher {
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,
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 35b2b123c..3e092d938 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -21,6 +21,7 @@ import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputTypeCompatUtils;
import com.android.inputmethod.keyboard.KeyboardId;
+import android.content.Context;
import android.content.res.Resources;
import android.inputmethodservice.InputMethodService;
import android.os.AsyncTask;
@@ -110,9 +111,14 @@ public class Utils {
}
public static String getInputMethodId(InputMethodManagerCompatWrapper imm, String packageName) {
+ return getInputMethodInfo(imm, packageName).getId();
+ }
+
+ public static InputMethodInfoCompatWrapper getInputMethodInfo(
+ InputMethodManagerCompatWrapper imm, String packageName) {
for (final InputMethodInfoCompatWrapper imi : imm.getEnabledInputMethodList()) {
if (imi.getPackageName().equals(packageName))
- return imi.getId();
+ return imi;
}
throw new RuntimeException("Can not find input method id for " + packageName);
}
@@ -601,4 +607,14 @@ public class Utils {
}
return true;
}
+
+ public static float getDipScale(Context context) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return scale;
+ }
+
+ /** Convert pixel to DIP */
+ public static int dipToPixel(float scale, int dip) {
+ return (int) ((float) dip * scale + 0.5);
+ }
}