Move some methods out from SubtypeSwitcher

Change-Id: I89aaf87d7d0cc204b0ca0f61c2f64d15e2df848e
main
Tadashi G. Takaoka 2014-11-06 13:16:20 +09:00
parent e1652d7570
commit 2a7da0ab87
9 changed files with 174 additions and 126 deletions

View File

@ -26,6 +26,8 @@ import com.android.inputmethod.latin.common.Constants;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import javax.annotation.Nonnull;
public final class InputMethodSubtypeCompatUtils { public final class InputMethodSubtypeCompatUtils {
private static final String TAG = InputMethodSubtypeCompatUtils.class.getSimpleName(); private static final String TAG = InputMethodSubtypeCompatUtils.class.getSimpleName();
// Note that InputMethodSubtype(int nameId, int iconId, String locale, String mode, // Note that InputMethodSubtype(int nameId, int iconId, String locale, String mode,
@ -53,6 +55,7 @@ public final class InputMethodSubtypeCompatUtils {
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Nonnull
public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale, public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale,
String mode, String extraValue, boolean isAuxiliary, String mode, String extraValue, boolean isAuxiliary,
boolean overridesImplicitlyEnabledSubtype, int id) { boolean overridesImplicitlyEnabledSubtype, int id) {

View File

@ -38,7 +38,6 @@ import com.android.inputmethod.keyboard.internal.KeysCache;
import com.android.inputmethod.latin.InputAttributes; import com.android.inputmethod.latin.InputAttributes;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.RichInputMethodSubtype; import com.android.inputmethod.latin.RichInputMethodSubtype;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.define.DebugFlags;
import com.android.inputmethod.latin.utils.InputTypeUtils; import com.android.inputmethod.latin.utils.InputTypeUtils;
import com.android.inputmethod.latin.utils.ScriptUtils; import com.android.inputmethod.latin.utils.ScriptUtils;
@ -276,7 +275,7 @@ public final class KeyboardLayoutSet {
mParams.mEditorInfo.imeOptions) mParams.mEditorInfo.imeOptions)
|| deprecatedForceAscii; || deprecatedForceAscii;
final RichInputMethodSubtype keyboardSubtype = (forceAscii && !asciiCapable) final RichInputMethodSubtype keyboardSubtype = (forceAscii && !asciiCapable)
? SubtypeSwitcher.getInstance().getNoLanguageSubtype() ? RichInputMethodSubtype.getNoLanguageSubtype()
: subtype; : subtype;
mParams.mSubtype = keyboardSubtype; mParams.mSubtype = keyboardSubtype;
mParams.mKeyboardLayoutSetName = KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX mParams.mKeyboardLayoutSetName = KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX

View File

@ -48,7 +48,7 @@ import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.latin.AudioAndHapticFeedbackManager; import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SubtypeSwitcher; import com.android.inputmethod.latin.RichInputMethodSubtype;
import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.common.Constants;
import com.android.inputmethod.latin.utils.ResourceUtils; import com.android.inputmethod.latin.utils.ResourceUtils;
@ -113,7 +113,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
context, null /* editorInfo */); context, null /* editorInfo */);
final Resources res = context.getResources(); final Resources res = context.getResources();
mEmojiLayoutParams = new EmojiLayoutParams(res); mEmojiLayoutParams = new EmojiLayoutParams(res);
builder.setSubtype(SubtypeSwitcher.getInstance().getEmojiSubtype()); builder.setSubtype(RichInputMethodSubtype.getEmojiSubtype());
builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res), builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res),
mEmojiLayoutParams.mEmojiKeyboardHeight); mEmojiLayoutParams.mEmojiKeyboardHeight);
final KeyboardLayoutSet layoutSet = builder.build(); final KeyboardLayoutSet layoutSet = builder.build();

View File

@ -626,7 +626,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void refreshPersonalizationDictionarySession( private void refreshPersonalizationDictionarySession(
final SettingsValues currentSettingsValues) { final SettingsValues currentSettingsValues) {
mDictionaryFacilitator.setIsMonolingualUser( mDictionaryFacilitator.setIsMonolingualUser(
mSubtypeSwitcher.isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes()); mRichImm.isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes());
mPersonalizationDictionaryUpdater.onLoadSettings( mPersonalizationDictionaryUpdater.onLoadSettings(
currentSettingsValues.mUsePersonalizedDicts); currentSettingsValues.mUsePersonalizedDicts);
mContextualDictionaryUpdater.onLoadSettings(currentSettingsValues.mUsePersonalizedDicts); mContextualDictionaryUpdater.onLoadSettings(currentSettingsValues.mUsePersonalizedDicts);
@ -863,7 +863,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// also wouldn't be consuming gesture data. // also wouldn't be consuming gesture data.
mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER; mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
mRichImm.clearSubtypeCaches(); mRichImm.clearSubtypeCaches();
mSubtypeSwitcher.refreshSubtypeInfo(); mSubtypeSwitcher.onSubtypeChanged(mRichImm.getCurrentRawSubtype());
final KeyboardSwitcher switcher = mKeyboardSwitcher; final KeyboardSwitcher switcher = mKeyboardSwitcher;
switcher.updateKeyboardTheme(); switcher.updateKeyboardTheme();
final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView(); final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();

View File

@ -29,6 +29,8 @@ import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
import com.android.inputmethod.latin.common.Constants;
import com.android.inputmethod.latin.settings.AdditionalFeaturesSettingUtils; import com.android.inputmethod.latin.settings.AdditionalFeaturesSettingUtils;
import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils; import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
@ -36,7 +38,10 @@ import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -432,4 +437,29 @@ public class RichInputMethodManager {
} }
return mImmWrapper.shouldOfferSwitchingToNextInputMethod(binder); return mImmWrapper.shouldOfferSwitchingToNextInputMethod(binder);
} }
public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() {
final Locale systemLocale = mContext.getResources().getConfiguration().locale;
final Set<InputMethodSubtype> enabledSubtypesOfEnabledImes = new HashSet<>();
final InputMethodManager inputMethodManager = getInputMethodManager();
final List<InputMethodInfo> enabledInputMethodInfoList =
inputMethodManager.getEnabledInputMethodList();
for (final InputMethodInfo info : enabledInputMethodInfoList) {
final List<InputMethodSubtype> enabledSubtypes =
inputMethodManager.getEnabledInputMethodSubtypeList(
info, true /* allowsImplicitlySelectedSubtypes */);
if (enabledSubtypes.isEmpty()) {
// An IME with no subtypes is found.
return false;
}
enabledSubtypesOfEnabledImes.addAll(enabledSubtypes);
}
for (final InputMethodSubtype subtype : enabledSubtypesOfEnabledImes) {
if (!subtype.isAuxiliary() && !subtype.getLocale().isEmpty()
&& !systemLocale.equals(SubtypeLocaleUtils.getSubtypeLocale(subtype))) {
return false;
}
}
return true;
}
} }

View File

@ -16,33 +16,45 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
import android.util.Log;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
import com.android.inputmethod.latin.common.Constants;
import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.LocaleUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import javax.annotation.Nonnull;
/** /**
* Enrichment class for InputMethodSubtype to enable concurrent multi-lingual input. * Enrichment class for InputMethodSubtype to enable concurrent multi-lingual input.
* *
* Right now, this returns the extra value of its primary subtype. * Right now, this returns the extra value of its primary subtype.
*/ */
public final class RichInputMethodSubtype { public final class RichInputMethodSubtype {
private static final String TAG = RichInputMethodSubtype.class.getSimpleName();
@Nonnull
private final InputMethodSubtype mSubtype; private final InputMethodSubtype mSubtype;
@Nonnull
private final Locale[] mLocales; private final Locale[] mLocales;
public RichInputMethodSubtype(final InputMethodSubtype subtype, final Locale... locales) { public RichInputMethodSubtype(@Nonnull final InputMethodSubtype subtype,
@Nonnull final Locale... locales) {
mSubtype = subtype; mSubtype = subtype;
mLocales = new Locale[locales.length+1]; mLocales = new Locale[locales.length + 1];
mLocales[0] = LocaleUtils.constructLocaleFromString(mSubtype.getLocale()); mLocales[0] = LocaleUtils.constructLocaleFromString(mSubtype.getLocale());
System.arraycopy(locales, 0, mLocales, 1, locales.length); System.arraycopy(locales, 0, mLocales, 1, locales.length);
} }
// Extra values are determined by the primary subtype. This is probably right, but // Extra values are determined by the primary subtype. This is probably right, but
// we may have to revisit this later. // we may have to revisit this later.
public String getExtraValueOf(final String key) { public String getExtraValueOf(@Nonnull final String key) {
return mSubtype.getExtraValueOf(key); return mSubtype.getExtraValueOf(key);
} }
@ -80,6 +92,7 @@ public final class RichInputMethodSubtype {
// en_US azerty T English English (US) // en_US azerty T English English (US)
// zz azerty T AZERTY AZERTY // zz azerty T AZERTY AZERTY
// Get the RichInputMethodSubtype's full display name in its locale. // Get the RichInputMethodSubtype's full display name in its locale.
@Nonnull
public String getFullDisplayName() { public String getFullDisplayName() {
if (isNoLanguage()) { if (isNoLanguage()) {
return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype); return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype);
@ -88,6 +101,7 @@ public final class RichInputMethodSubtype {
} }
// Get the RichInputMethodSubtype's middle display name in its locale. // Get the RichInputMethodSubtype's middle display name in its locale.
@Nonnull
public String getMiddleDisplayName() { public String getMiddleDisplayName() {
if (isNoLanguage()) { if (isNoLanguage()) {
return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype); return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype);
@ -96,7 +110,7 @@ public final class RichInputMethodSubtype {
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(final Object o) {
if (!(o instanceof RichInputMethodSubtype)) { if (!(o instanceof RichInputMethodSubtype)) {
return false; return false;
} }
@ -114,6 +128,7 @@ public final class RichInputMethodSubtype {
return "Multi-lingual subtype: " + mSubtype.toString() + ", " + Arrays.toString(mLocales); return "Multi-lingual subtype: " + mSubtype.toString() + ", " + Arrays.toString(mLocales);
} }
@Nonnull
public Locale[] getLocales() { public Locale[] getLocales() {
return mLocales; return mLocales;
} }
@ -124,5 +139,80 @@ public final class RichInputMethodSubtype {
} }
// TODO: remove this method // TODO: remove this method
@Nonnull
public InputMethodSubtype getRawSubtype() { return mSubtype; } public InputMethodSubtype getRawSubtype() { return mSubtype; }
// Dummy no language QWERTY subtype. See {@link R.xml.method}.
private static final int SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE = 0xdde0bfd3;
private static final String EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE =
"KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY
+ "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
+ "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE
+ "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
@Nonnull
private static final RichInputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE =
new RichInputMethodSubtype(InputMethodSubtypeCompatUtils.newInputMethodSubtype(
R.string.subtype_no_language_qwerty, R.drawable.ic_ime_switcher_dark,
SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE,
false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE));
// Caveat: We probably should remove this when we add an Emoji subtype in {@link R.xml.method}.
// Dummy Emoji subtype. See {@link R.xml.method}.
private static final int SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE = 0xd78b2ed0;
private static final String EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE =
"KeyboardLayoutSet=" + SubtypeLocaleUtils.EMOJI
+ "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
@Nonnull
private static final RichInputMethodSubtype DUMMY_EMOJI_SUBTYPE = new RichInputMethodSubtype(
InputMethodSubtypeCompatUtils.newInputMethodSubtype(
R.string.subtype_emoji, R.drawable.ic_ime_switcher_dark,
SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE,
false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE));
private static RichInputMethodSubtype sNoLanguageSubtype;
private static RichInputMethodSubtype sEmojiSubtype;
@Nonnull
public static RichInputMethodSubtype getNoLanguageSubtype() {
RichInputMethodSubtype noLanguageSubtype = sNoLanguageSubtype;
if (noLanguageSubtype == null) {
final InputMethodSubtype rawNoLanguageSubtype = RichInputMethodManager.getInstance()
.findSubtypeByLocaleAndKeyboardLayoutSet(
SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
if (rawNoLanguageSubtype != null) {
noLanguageSubtype = new RichInputMethodSubtype(rawNoLanguageSubtype);
}
}
if (noLanguageSubtype != null) {
sNoLanguageSubtype = noLanguageSubtype;
return noLanguageSubtype;
}
Log.w(TAG, "Can't find any language with QWERTY subtype");
Log.w(TAG, "No input method subtype found; returning dummy subtype: "
+ DUMMY_NO_LANGUAGE_SUBTYPE);
return DUMMY_NO_LANGUAGE_SUBTYPE;
}
@Nonnull
public static RichInputMethodSubtype getEmojiSubtype() {
RichInputMethodSubtype emojiSubtype = sEmojiSubtype;
if (emojiSubtype == null) {
final InputMethodSubtype rawEmojiSubtype = RichInputMethodManager.getInstance()
.findSubtypeByLocaleAndKeyboardLayoutSet(
SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.EMOJI);
if (rawEmojiSubtype != null) {
emojiSubtype = new RichInputMethodSubtype(rawEmojiSubtype);
}
}
if (emojiSubtype != null) {
sEmojiSubtype = emojiSubtype;
return emojiSubtype;
}
Log.w(TAG, "Can't find emoji subtype");
Log.w(TAG, "No input method subtype found; returning dummy subtype: "
+ DUMMY_EMOJI_SUBTYPE);
return DUMMY_EMOJI_SUBTYPE;
}
} }

View File

@ -17,6 +17,7 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY; import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
@ -31,18 +32,14 @@ import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper; import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
import com.android.inputmethod.latin.common.Constants;
import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.define.DebugFlags;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -60,39 +57,8 @@ public final class SubtypeSwitcher {
private InputMethodInfo mShortcutInputMethodInfo; private InputMethodInfo mShortcutInputMethodInfo;
private InputMethodSubtype mShortcutSubtype; private InputMethodSubtype mShortcutSubtype;
private RichInputMethodSubtype mCurrentRichInputMethodSubtype; private RichInputMethodSubtype mCurrentRichInputMethodSubtype;
private RichInputMethodSubtype mNoLanguageSubtype;
private RichInputMethodSubtype mEmojiSubtype;
private boolean mIsNetworkConnected; private boolean mIsNetworkConnected;
private static final String KEYBOARD_MODE = "keyboard";
// Dummy no language QWERTY subtype. See {@link R.xml.method}.
private static final int SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE = 0xdde0bfd3;
private static final String EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE =
"KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY
+ "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
+ "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE
+ "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
private static final RichInputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE =
new RichInputMethodSubtype(InputMethodSubtypeCompatUtils.newInputMethodSubtype(
R.string.subtype_no_language_qwerty, R.drawable.ic_ime_switcher_dark,
SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE,
false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE));
// Caveat: We probably should remove this when we add an Emoji subtype in {@link R.xml.method}.
// Dummy Emoji subtype. See {@link R.xml.method}.
private static final int SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE = 0xd78b2ed0;
private static final String EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE =
"KeyboardLayoutSet=" + SubtypeLocaleUtils.EMOJI
+ "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
private static final RichInputMethodSubtype DUMMY_EMOJI_SUBTYPE = new RichInputMethodSubtype(
InputMethodSubtypeCompatUtils.newInputMethodSubtype(
R.string.subtype_emoji, R.drawable.ic_ime_switcher_dark,
SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE,
false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE));
public static SubtypeSwitcher getInstance() { public static SubtypeSwitcher getInstance() {
return sInstance; return sInstance;
} }
@ -119,12 +85,8 @@ public final class SubtypeSwitcher {
final NetworkInfo info = connectivityManager.getActiveNetworkInfo(); final NetworkInfo info = connectivityManager.getActiveNetworkInfo();
mIsNetworkConnected = (info != null && info.isConnected()); mIsNetworkConnected = (info != null && info.isConnected());
refreshSubtypeInfo();
updateParametersOnStartInputView();
}
public void refreshSubtypeInfo() {
onSubtypeChanged(mRichImm.getCurrentRawSubtype()); onSubtypeChanged(mRichImm.getCurrentRawSubtype());
updateParametersOnStartInputView();
} }
/** /**
@ -267,31 +229,6 @@ public final class SubtypeSwitcher {
return mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(subtype); return mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(subtype);
} }
public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() {
final Locale systemLocale = mResources.getConfiguration().locale;
final Set<InputMethodSubtype> enabledSubtypesOfEnabledImes = new HashSet<>();
final InputMethodManager inputMethodManager = mRichImm.getInputMethodManager();
final List<InputMethodInfo> enabledInputMethodInfoList =
inputMethodManager.getEnabledInputMethodList();
for (final InputMethodInfo info : enabledInputMethodInfoList) {
final List<InputMethodSubtype> enabledSubtypes =
inputMethodManager.getEnabledInputMethodSubtypeList(
info, true /* allowsImplicitlySelectedSubtypes */);
if (enabledSubtypes.isEmpty()) {
// An IME with no subtypes is found.
return false;
}
enabledSubtypesOfEnabledImes.addAll(enabledSubtypes);
}
for (final InputMethodSubtype subtype : enabledSubtypesOfEnabledImes) {
if (!subtype.isAuxiliary() && !subtype.getLocale().isEmpty()
&& !systemLocale.equals(SubtypeLocaleUtils.getSubtypeLocale(subtype))) {
return false;
}
}
return true;
}
private static RichInputMethodSubtype sForcedSubtypeForTesting = null; private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
@UsedForTesting @UsedForTesting
@ -313,39 +250,6 @@ public final class SubtypeSwitcher {
return mCurrentRichInputMethodSubtype; return mCurrentRichInputMethodSubtype;
} }
public RichInputMethodSubtype getNoLanguageSubtype() {
if (mNoLanguageSubtype == null) {
mNoLanguageSubtype = new RichInputMethodSubtype(
mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY));
}
if (mNoLanguageSubtype != null) {
return mNoLanguageSubtype;
}
Log.w(TAG, "Can't find any language with QWERTY subtype");
Log.w(TAG, "No input method subtype found; returning dummy subtype: "
+ DUMMY_NO_LANGUAGE_SUBTYPE);
return DUMMY_NO_LANGUAGE_SUBTYPE;
}
public RichInputMethodSubtype getEmojiSubtype() {
if (mEmojiSubtype == null) {
final InputMethodSubtype rawEmojiSubtype =
mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.EMOJI);
if (null != rawEmojiSubtype) {
mEmojiSubtype = new RichInputMethodSubtype(rawEmojiSubtype);
}
}
if (mEmojiSubtype != null) {
return mEmojiSubtype;
}
Log.w(TAG, "Can't find emoji subtype");
Log.w(TAG, "No input method subtype found; returning dummy subtype: "
+ DUMMY_EMOJI_SUBTYPE);
return DUMMY_EMOJI_SUBTYPE;
}
public String getCombiningRulesExtraValueOfCurrentSubtype() { public String getCombiningRulesExtraValueOfCurrentSubtype() {
return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype().getRawSubtype()); return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype().getRawSubtype());
} }

View File

@ -21,6 +21,8 @@ import android.text.TextUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import javax.annotation.Nullable;
/** /**
* A class to help with handling Locales in string form. * A class to help with handling Locales in string form.
* *
@ -164,8 +166,10 @@ public final class LocaleUtils {
/** /**
* Creates a locale from a string specification. * Creates a locale from a string specification.
*/ */
public static Locale constructLocaleFromString(final String localeStr) { @Nullable
public static Locale constructLocaleFromString(@Nullable final String localeStr) {
if (localeStr == null) { if (localeStr == null) {
// TODO: Should this be Locale.ROOT?
return null; return null;
} }
synchronized (sLocaleCache) { synchronized (sLocaleCache) {
@ -173,7 +177,7 @@ public final class LocaleUtils {
if (retval != null) { if (retval != null) {
return retval; return retval;
} }
String[] localeParams = localeStr.split("_", 3); final String[] localeParams = localeStr.split("_", 3);
if (localeParams.length == 1) { if (localeParams.length == 1) {
retval = new Locale(localeParams[0]); retval = new Locale(localeParams[0]);
} else if (localeParams.length == 2) { } else if (localeParams.length == 2) {
@ -184,6 +188,7 @@ public final class LocaleUtils {
if (retval != null) { if (retval != null) {
sLocaleCache.put(localeStr, retval); sLocaleCache.put(localeStr, retval);
} }
// TODO: Should return Locale.ROOT instead of null?
return retval; return retval;
} }
} }

View File

@ -34,6 +34,8 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import javax.annotation.Nonnull;
/** /**
* A helper class to deal with subtype locales. * A helper class to deal with subtype locales.
*/ */
@ -173,7 +175,8 @@ public final class SubtypeLocaleUtils {
return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId; return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId;
} }
public static Locale getDisplayLocaleOfSubtypeLocale(final String localeString) { @Nonnull
public static Locale getDisplayLocaleOfSubtypeLocale(@Nonnull final String localeString) {
if (NO_LANGUAGE.equals(localeString)) { if (NO_LANGUAGE.equals(localeString)) {
return sResources.getConfiguration().locale; return sResources.getConfiguration().locale;
} }
@ -183,17 +186,20 @@ public final class SubtypeLocaleUtils {
return LocaleUtils.constructLocaleFromString(localeString); return LocaleUtils.constructLocaleFromString(localeString);
} }
public static String getSubtypeLocaleDisplayNameInSystemLocale(final String localeString) { public static String getSubtypeLocaleDisplayNameInSystemLocale(
@Nonnull final String localeString) {
final Locale displayLocale = sResources.getConfiguration().locale; final Locale displayLocale = sResources.getConfiguration().locale;
return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale); return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
} }
public static String getSubtypeLocaleDisplayName(final String localeString) { @Nonnull
public static String getSubtypeLocaleDisplayName(@Nonnull final String localeString) {
final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString); final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale); return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
} }
public static String getSubtypeLanguageDisplayName(final String localeString) { @Nonnull
public static String getSubtypeLanguageDisplayName(@Nonnull final String localeString) {
final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString); final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
final String languageString; final String languageString;
if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) { if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
@ -205,8 +211,9 @@ public final class SubtypeLocaleUtils {
return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale); return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale);
} }
private static String getSubtypeLocaleDisplayNameInternal(final String localeString, @Nonnull
final Locale displayLocale) { private static String getSubtypeLocaleDisplayNameInternal(@Nonnull final String localeString,
@Nonnull final Locale displayLocale) {
if (NO_LANGUAGE.equals(localeString)) { if (NO_LANGUAGE.equals(localeString)) {
// No language subtype should be displayed in system locale. // No language subtype should be displayed in system locale.
return sResources.getString(R.string.subtype_no_language); return sResources.getString(R.string.subtype_no_language);
@ -255,8 +262,9 @@ public final class SubtypeLocaleUtils {
// en_US azerty T English (US) (AZERTY) exception // en_US azerty T English (US) (AZERTY) exception
// zz azerty T Alphabet (AZERTY) in system locale // zz azerty T Alphabet (AZERTY) in system locale
private static String getReplacementString(final InputMethodSubtype subtype, @Nonnull
final Locale displayLocale) { private static String getReplacementString(@Nonnull final InputMethodSubtype subtype,
@Nonnull final Locale displayLocale) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) { && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME); return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
@ -264,20 +272,24 @@ public final class SubtypeLocaleUtils {
return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale); return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
} }
public static String getSubtypeDisplayNameInSystemLocale(final InputMethodSubtype subtype) { @Nonnull
public static String getSubtypeDisplayNameInSystemLocale(
@Nonnull final InputMethodSubtype subtype) {
final Locale displayLocale = sResources.getConfiguration().locale; final Locale displayLocale = sResources.getConfiguration().locale;
return getSubtypeDisplayNameInternal(subtype, displayLocale); return getSubtypeDisplayNameInternal(subtype, displayLocale);
} }
public static String getSubtypeNameForLogging(final InputMethodSubtype subtype) { @Nonnull
public static String getSubtypeNameForLogging(@Nonnull final InputMethodSubtype subtype) {
if (subtype == null) { if (subtype == null) {
return "<null subtype>"; return "<null subtype>";
} }
return getSubtypeLocale(subtype) + "/" + getKeyboardLayoutSetName(subtype); return getSubtypeLocale(subtype) + "/" + getKeyboardLayoutSetName(subtype);
} }
private static String getSubtypeDisplayNameInternal(final InputMethodSubtype subtype, @Nonnull
final Locale displayLocale) { private static String getSubtypeDisplayNameInternal(@Nonnull final InputMethodSubtype subtype,
@Nonnull final Locale displayLocale) {
final String replacementString = getReplacementString(subtype, displayLocale); final String replacementString = getReplacementString(subtype, displayLocale);
// TODO: rework this for multi-lingual subtypes // TODO: rework this for multi-lingual subtypes
final int nameResId = subtype.getNameResId(); final int nameResId = subtype.getNameResId();
@ -302,21 +314,26 @@ public final class SubtypeLocaleUtils {
getSubtypeName.runInLocale(sResources, displayLocale), displayLocale); getSubtypeName.runInLocale(sResources, displayLocale), displayLocale);
} }
public static Locale getSubtypeLocale(final InputMethodSubtype subtype) { @Nonnull
public static Locale getSubtypeLocale(@Nonnull final InputMethodSubtype subtype) {
final String localeString = subtype.getLocale(); final String localeString = subtype.getLocale();
return LocaleUtils.constructLocaleFromString(localeString); return LocaleUtils.constructLocaleFromString(localeString);
} }
public static String getKeyboardLayoutSetDisplayName(final InputMethodSubtype subtype) { @Nonnull
public static String getKeyboardLayoutSetDisplayName(
@Nonnull final InputMethodSubtype subtype) {
final String layoutName = getKeyboardLayoutSetName(subtype); final String layoutName = getKeyboardLayoutSetName(subtype);
return getKeyboardLayoutSetDisplayName(layoutName); return getKeyboardLayoutSetDisplayName(layoutName);
} }
public static String getKeyboardLayoutSetDisplayName(final String layoutName) { @Nonnull
public static String getKeyboardLayoutSetDisplayName(@Nonnull final String layoutName) {
return sKeyboardLayoutToDisplayNameMap.get(layoutName); return sKeyboardLayoutToDisplayNameMap.get(layoutName);
} }
public static String getKeyboardLayoutSetName(final RichInputMethodSubtype subtype) { @Nonnull
public static String getKeyboardLayoutSetName(@Nonnull final RichInputMethodSubtype subtype) {
return getKeyboardLayoutSetName(subtype.getRawSubtype()); return getKeyboardLayoutSetName(subtype.getRawSubtype());
} }