diff options
Diffstat (limited to 'java/src')
10 files changed, 250 insertions, 54 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java index 955cb4c42..67e21b10c 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java @@ -18,13 +18,18 @@ package com.android.inputmethod.accessibility; import android.graphics.Rect; import android.inputmethodservice.InputMethodService; +import android.os.Bundle; +import android.os.SystemClock; import android.support.v4.view.ViewCompat; +import android.support.v4.view.accessibility.AccessibilityEventCompat; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat; import android.support.v4.view.accessibility.AccessibilityRecordCompat; import android.util.Log; import android.util.SparseArray; +import android.view.MotionEvent; import android.view.View; +import android.view.ViewParent; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.accessibility.AccessibilityEvent; import android.view.inputmethod.EditorInfo; @@ -45,6 +50,7 @@ import com.android.inputmethod.keyboard.KeyboardView; */ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat { private static final String TAG = AccessibilityEntityProvider.class.getSimpleName(); + private static final int UNDEFINED = Integer.MIN_VALUE; private final KeyboardView mKeyboardView; private final InputMethodService mInputMethodService; @@ -60,6 +66,9 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat /** The parent view's cached on-screen location. */ private final int[] mParentLocation = new int[2]; + /** The virtual view identifier for the focused node. */ + private int mAccessibilityFocusedView = UNDEFINED; + public AccessibilityEntityProvider(KeyboardView keyboardView, InputMethodService inputMethod) { mKeyboardView = keyboardView; mInputMethodService = inputMethod; @@ -124,7 +133,9 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) { AccessibilityNodeInfoCompat info = null; - if (virtualViewId == View.NO_ID) { + if (virtualViewId == UNDEFINED) { + return null; + } else if (virtualViewId == View.NO_ID) { // We are requested to create an AccessibilityNodeInfo describing // this View, i.e. the root of the virtual sub-tree. info = AccessibilityNodeInfoCompat.obtain(mKeyboardView); @@ -166,12 +177,115 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat info.setSource(mKeyboardView, virtualViewId); info.setBoundsInScreen(boundsInScreen); info.setEnabled(true); + info.setClickable(true); + info.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK); + + if (mAccessibilityFocusedView == virtualViewId) { + info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS); + } else { + info.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS); + } } return info; } /** + * Simulates a key press by injecting touch events into the keyboard view. + * This avoids the complexity of trackers and listeners within the keyboard. + * + * @param key The key to press. + */ + void simulateKeyPress(Key key) { + final int x = key.mX + (key.mWidth / 2); + final int y = key.mY + (key.mHeight / 2); + final long downTime = SystemClock.uptimeMillis(); + final MotionEvent downEvent = MotionEvent.obtain( + downTime, downTime, MotionEvent.ACTION_DOWN, x, y, 0); + final MotionEvent upEvent = MotionEvent.obtain( + downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0); + + mKeyboardView.onTouchEvent(downEvent); + mKeyboardView.onTouchEvent(upEvent); + } + + @Override + public boolean performAction(int virtualViewId, int action, Bundle arguments) { + final Key key = mVirtualViewIdToKey.get(virtualViewId); + + if (key == null) { + return false; + } + + return performActionForKey(key, action, arguments); + } + + /** + * Performs the specified accessibility action for the given key. + * + * @param key The on which to perform the action. + * @param action The action to perform. + * @param arguments The action's arguments. + * @return The result of performing the action, or false if the action is + * not supported. + */ + boolean performActionForKey(Key key, int action, Bundle arguments) { + final int virtualViewId = generateVirtualViewIdForKey(key); + + switch (action) { + case AccessibilityNodeInfoCompat.ACTION_CLICK: + simulateKeyPress(key); + return true; + case AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS: + if (mAccessibilityFocusedView == virtualViewId) { + return false; + } + mAccessibilityFocusedView = virtualViewId; + sendAccessibilityEventForKey( + key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED); + return true; + case AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS: + if (mAccessibilityFocusedView != virtualViewId) { + return false; + } + mAccessibilityFocusedView = UNDEFINED; + sendAccessibilityEventForKey( + key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); + return true; + } + + return false; + } + + @Override + public AccessibilityNodeInfoCompat findAccessibilityFocus(int virtualViewId) { + return createAccessibilityNodeInfo(mAccessibilityFocusedView); + } + + @Override + public AccessibilityNodeInfoCompat accessibilityFocusSearch(int direction, int virtualViewId) { + // Focus search is not currently supported for IMEs. + return null; + } + + /** + * Sends an accessibility event for the given {@link Key}. + * + * @param key The key that's sending the event. + * @param eventType The type of event to send. + */ + void sendAccessibilityEventForKey(Key key, int eventType) { + final AccessibilityEvent event = createAccessibilityEvent(key, eventType); + final ViewParent parent = mKeyboardView.getParent(); + + if (parent == null) { + return; + } + + parent.requestSendAccessibilityEvent(mKeyboardView, event); + } + + /** * Returns the context-specific description for a {@link Key}. * * @param key The key to describe. diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java index 34817ba4e..1b0e488bc 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java @@ -21,10 +21,10 @@ import android.inputmethodservice.InputMethodService; import android.support.v4.view.AccessibilityDelegateCompat; import android.support.v4.view.ViewCompat; import android.support.v4.view.accessibility.AccessibilityEventCompat; +import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; -import android.view.accessibility.AccessibilityEvent; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; @@ -91,13 +91,7 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { */ @Override public AccessibilityEntityProvider getAccessibilityNodeProvider(View host) { - // Instantiate the provide only when requested. Since the system - // will call this method multiple times it is a good practice to - // cache the provider instance. - if (mAccessibilityNodeProvider == null) { - mAccessibilityNodeProvider = new AccessibilityEntityProvider(mView, mInputMethod); - } - return mAccessibilityNodeProvider; + return getAccessibilityNodeProvider(); } /** @@ -120,7 +114,7 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { // Make sure we're not getting an EXIT event because the user slid // off the keyboard area, then force a key press. if (pointInView(x, y)) { - tracker.onRegisterKey(key); + getAccessibilityNodeProvider().simulateKeyPress(key); } //$FALL-THROUGH$ case MotionEvent.ACTION_HOVER_ENTER: @@ -137,6 +131,19 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { } /** + * @return A lazily-instantiated node provider for this view proxy. + */ + private AccessibilityEntityProvider getAccessibilityNodeProvider() { + // Instantiate the provide only when requested. Since the system + // will call this method multiple times it is a good practice to + // cache the provider instance. + if (mAccessibilityNodeProvider == null) { + mAccessibilityNodeProvider = new AccessibilityEntityProvider(mView, mInputMethod); + } + return mAccessibilityNodeProvider; + } + + /** * Utility method to determine whether the given point, in local * coordinates, is inside the view, where the area of the view is contracted * by the edge slop factor. @@ -191,12 +198,18 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { return false; } + final AccessibilityEntityProvider provider = getAccessibilityNodeProvider(); + switch (event.getAction()) { case MotionEvent.ACTION_HOVER_ENTER: - sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER); + provider.sendAccessibilityEventForKey( + key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER); + provider.performActionForKey( + key, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS, null); break; case MotionEvent.ACTION_HOVER_EXIT: - sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT); + provider.sendAccessibilityEventForKey( + key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT); break; } @@ -204,20 +217,6 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { } /** - * Populates and sends an {@link AccessibilityEvent} for the specified key. - * - * @param key The key to send an event for. - * @param eventType The type of event to send. - */ - private void sendAccessibilityEventForKey(Key key, int eventType) { - final AccessibilityEntityProvider nodeProvider = getAccessibilityNodeProvider(null); - final AccessibilityEvent event = nodeProvider.createAccessibilityEvent(key, eventType); - - // Propagates the event up the view hierarchy. - mView.getParent().requestSendAccessibilityEvent(mView, event); - } - - /** * Notifies the user of changes in the keyboard shift state. */ public void notifyShiftState() { diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java index 3d861c231..f4e4105e3 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java +++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java @@ -111,6 +111,9 @@ public class KeyCodeDescriptionMapper { if (mKeyLabelMap.containsKey(label)) { return context.getString(mKeyLabelMap.get(label)); } + + // Otherwise, return the label. + return key.mLabel; } // Just attempt to speak the description. diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index bd3b0e114..0be4cf3a7 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -197,6 +197,20 @@ public class Keyboard { return null; } + public boolean hasKey(Key aKey) { + if (mKeyCache.containsKey(aKey)) { + return true; + } + + for (final Key key : mKeys) { + if (key == aKey) { + mKeyCache.put(key.mCode, key); + return true; + } + } + return false; + } + public static boolean isLetterCode(int code) { return code >= MINIMUM_LETTER_CODE; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index c0d5b6772..cc0a1fb10 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -487,6 +487,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } else { // Draw invalidated keys. for (final Key key : mInvalidatedKeys) { + if (!mKeyboard.hasKey(key)) { + continue; + } final int x = key.mX + getPaddingLeft(); final int y = key.mY + getPaddingTop(); mInvalidatedKeysRect.set(x, y, x + key.mWidth, y + key.mHeight); diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java index a8115fb82..779a38823 100644 --- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java +++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; +import android.content.res.Resources; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -41,9 +42,11 @@ import android.view.inputmethod.InputMethodSubtype; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.SpinnerAdapter; +import android.widget.Toast; import com.android.inputmethod.compat.CompatUtils; +import java.util.ArrayList; import java.util.TreeSet; public class AdditionalSubtypeSettings extends PreferenceFragment { @@ -60,7 +63,6 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { private static final String KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN = "is_subtype_enabler_notification_dialog_open"; private static final String KEY_SUBTYPE_FOR_SUBTYPE_ENABLER = "subtype_for_subtype_enabler"; - static class SubtypeLocaleItem extends Pair<String, String> implements Comparable<SubtypeLocaleItem> { public SubtypeLocaleItem(String localeString, String displayName) { @@ -139,6 +141,7 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { private interface SubtypeDialogProxy { public void onRemovePressed(SubtypePreference subtypePref); + public void onSavePressed(SubtypePreference subtypePref); public void onAddPressed(SubtypePreference subtypePref); public SubtypeLocaleAdapter getSubtypeLocaleAdapter(); public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter(); @@ -150,6 +153,7 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { private static final String KEY_NEW_SUBTYPE = KEY_PREFIX + "new"; private InputMethodSubtype mSubtype; + private InputMethodSubtype mPreviousSubtype; private final SubtypeDialogProxy mProxy; private Spinner mSubtypeLocaleSpinner; @@ -182,6 +186,7 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { } public void setSubtype(InputMethodSubtype subtype) { + mPreviousSubtype = mSubtype; mSubtype = subtype; if (isIncomplete()) { setTitle(null); @@ -197,6 +202,14 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { } } + public void revert() { + setSubtype(mPreviousSubtype); + } + + public boolean hasBeenModified() { + return mSubtype != null && !mSubtype.equals(mPreviousSubtype); + } + @Override protected View onCreateDialogView() { final View v = super.onCreateDialogView(); @@ -250,7 +263,7 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { super.onClick(dialog, which); switch (which) { case DialogInterface.BUTTON_POSITIVE: - final boolean addPressed = isIncomplete(); + final boolean isEditing = !isIncomplete(); final SubtypeLocaleItem locale = (SubtypeLocaleItem) mSubtypeLocaleSpinner.getSelectedItem(); final KeyboardLayoutSetItem layout = @@ -259,7 +272,9 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { locale.first, layout.first, ASCII_CAPABLE); setSubtype(subtype); notifyChanged(); - if (addPressed) { + if (isEditing) { + mProxy.onSavePressed(this); + } else { mProxy.onAddPressed(this); } break; @@ -414,18 +429,45 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { public void onRemovePressed(SubtypePreference subtypePref) { mIsAddingNewSubtype = false; final PreferenceGroup group = getPreferenceScreen(); - if (group != null) { - group.removePreference(subtypePref); + group.removePreference(subtypePref); + ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), getSubtypes()); + } + + @Override + public void onSavePressed(SubtypePreference subtypePref) { + final InputMethodSubtype subtype = subtypePref.getSubtype(); + if (!subtypePref.hasBeenModified()) { + return; } + if (findDuplicatedSubtype(subtype) == null) { + ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), getSubtypes()); + return; + } + + // Saved subtype is duplicated. + final PreferenceGroup group = getPreferenceScreen(); + group.removePreference(subtypePref); + subtypePref.revert(); + group.addPreference(subtypePref); + showSubtypeAlreadyExistsToast(subtype); } @Override public void onAddPressed(SubtypePreference subtypePref) { mIsAddingNewSubtype = false; - setAdditionalInputMethodSubtypes(getPrefSubtypes()); - mSubtypePreferenceKeyForSubtypeEnabler = subtypePref.getKey(); - mSubtypeEnablerNotificationDialog = createDialog(subtypePref); - mSubtypeEnablerNotificationDialog.show(); + final InputMethodSubtype subtype = subtypePref.getSubtype(); + if (findDuplicatedSubtype(subtype) == null) { + ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), getSubtypes()); + mSubtypePreferenceKeyForSubtypeEnabler = subtypePref.getKey(); + mSubtypeEnablerNotificationDialog = createDialog(subtypePref); + mSubtypeEnablerNotificationDialog.show(); + return; + } + + // Newly added subtype is duplicated. + final PreferenceGroup group = getPreferenceScreen(); + group.removePreference(subtypePref); + showSubtypeAlreadyExistsToast(subtype); } @Override @@ -439,6 +481,21 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { } }; + private void showSubtypeAlreadyExistsToast(InputMethodSubtype subtype) { + final Context context = getActivity(); + final Resources res = context.getResources(); + final String message = res.getString(R.string.custom_input_style_already_exists, + SubtypeLocale.getSubtypeDisplayName(subtype, res)); + Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); + } + + private InputMethodSubtype findDuplicatedSubtype(InputMethodSubtype subtype) { + final String localeString = subtype.getLocale(); + final String keyboardLayoutSetName = SubtypeLocale.getKeyboardLayoutSetName(subtype); + return ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet( + getActivity(), localeString, keyboardLayoutSetName); + } + private AlertDialog createDialog(SubtypePreference subtypePref) { final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.custom_input_styles_title) @@ -474,9 +531,9 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { } } - private String getPrefSubtypes() { + private InputMethodSubtype[] getSubtypes() { final PreferenceGroup group = getPreferenceScreen(); - final StringBuilder sb = new StringBuilder(); + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); final int count = group.getPreferenceCount(); for (int i = 0; i < count; i++) { final Preference pref = group.getPreference(i); @@ -484,13 +541,20 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { final SubtypePreference subtypePref = (SubtypePreference)pref; // We should not save newly adding subtype to preference because it is incomplete. if (subtypePref.isIncomplete()) continue; - final InputMethodSubtype subtype = subtypePref.getSubtype(); - if (sb.length() > 0) { - sb.append(AdditionalSubtype.PREF_SUBTYPE_SEPARATOR); - } - sb.append(AdditionalSubtype.getPrefSubtype(subtype)); + subtypes.add(subtypePref.getSubtype()); } } + return subtypes.toArray(new InputMethodSubtype[subtypes.size()]); + } + + private String getPrefSubtypes(InputMethodSubtype[] subtypes) { + final StringBuilder sb = new StringBuilder(); + for (final InputMethodSubtype subtype : subtypes) { + if (sb.length() > 0) { + sb.append(AdditionalSubtype.PREF_SUBTYPE_SEPARATOR); + } + sb.append(AdditionalSubtype.getPrefSubtype(subtype)); + } return sb.toString(); } @@ -498,7 +562,8 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { public void onPause() { super.onPause(); final String oldSubtypes = SettingsValues.getPrefAdditionalSubtypes(mPrefs, getResources()); - final String prefSubtypes = getPrefSubtypes(); + final InputMethodSubtype[] subtypes = getSubtypes(); + final String prefSubtypes = getPrefSubtypes(subtypes); if (prefSubtypes.equals(oldSubtypes)) { return; } @@ -509,12 +574,6 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { } finally { editor.apply(); } - setAdditionalInputMethodSubtypes(prefSubtypes); - } - - private void setAdditionalInputMethodSubtypes(final String prefSubtypes) { - final InputMethodSubtype[] subtypes = - AdditionalSubtype.createAdditionalSubtypesArray(prefSubtypes); ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), subtypes); } diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java index 93106ac27..0f34d50bb 100644 --- a/java/src/com/android/inputmethod/latin/EditingUtils.java +++ b/java/src/com/android/inputmethod/latin/EditingUtils.java @@ -29,7 +29,8 @@ public class EditingUtils { /** * Number of characters we want to look back in order to identify the previous word */ - private static final int LOOKBACK_CHARACTER_NUM = 15; + // Provision for a long word pair and a separator + private static final int LOOKBACK_CHARACTER_NUM = BinaryDictionary.MAX_WORD_LENGTH * 2 + 1; private static final int INVALID_CURSOR_POSITION = -1; private EditingUtils() { diff --git a/java/src/com/android/inputmethod/latin/ImfUtils.java b/java/src/com/android/inputmethod/latin/ImfUtils.java index 36f6d8ba0..b882a4860 100644 --- a/java/src/com/android/inputmethod/latin/ImfUtils.java +++ b/java/src/com/android/inputmethod/latin/ImfUtils.java @@ -167,8 +167,7 @@ public class ImfUtils { return subtype; } } - throw new RuntimeException("Can't find subtype for locale " + localeString - + " and keyboard layout " + keyboardLayoutSetName); + return null; } public static void setAdditionalInputMethodSubtypes(Context context, diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index b59e939b7..261755f53 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1298,8 +1298,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen break; } switcher.onCodeInput(primaryCode); - // Reset after any single keystroke - if (!didAutoCorrect) + // Reset after any single keystroke, except shift and symbol-shift + if (!didAutoCorrect && primaryCode != Keyboard.CODE_SHIFT + && primaryCode != Keyboard.CODE_SWITCH_ALPHA_SYMBOL) mLastComposedWord.deactivate(); mEnteredText = null; } diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index f2d971ca4..664de6774 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -101,6 +101,9 @@ public class SubtypeSwitcher { mCurrentSubtype = mImm.getCurrentInputMethodSubtype(); mNoLanguageSubtype = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet( service, SubtypeLocale.NO_LANGUAGE, SubtypeLocale.QWERTY); + if (mNoLanguageSubtype == null) { + throw new RuntimeException("Can't find no lanugage with QWERTY subtype"); + } final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); mIsNetworkConnected = (info != null && info.isConnected()); |