public boolean isShortcutImeReady() {
   if (mShortcutInputMethodInfo == null) return false;
   if (mShortcutSubtype == null) return true;
   if (contains(
       mShortcutSubtype.getExtraValue().split(","),
       SUBTYPE_EXTRAVALUE_REQUIRE_NETWORK_CONNECTIVITY)) {
     return mIsNetworkConnected;
   }
   return true;
 }
 public String getCurrentSubtypeExtraValue() {
   // If null, return what an empty ExtraValue would return : the empty string.
   return null != mCurrentSubtype ? mCurrentSubtype.getExtraValue() : "";
 }
  // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
  public void updateSubtype(InputMethodSubtypeCompatWrapper newSubtype) {
    final String newLocale;
    final String newMode;
    final String oldMode = getCurrentSubtypeMode();
    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.");
      newLocale = "en_US";
      newMode = KEYBOARD_MODE;
    } else {
      newLocale = getSubtypeLocale(newSubtype);
      newMode = newSubtype.getMode();
    }
    if (DBG) {
      Log.w(
          TAG,
          "Update subtype to:"
              + newLocale
              + ","
              + newMode
              + ", from: "
              + mInputLocaleStr
              + ", "
              + oldMode);
    }
    boolean languageChanged = false;
    if (!newLocale.equals(mInputLocaleStr)) {
      if (mInputLocaleStr != null) {
        languageChanged = true;
      }
      updateInputLocale(newLocale);
    }
    boolean modeChanged = false;
    if (!newMode.equals(oldMode)) {
      if (oldMode != null) {
        modeChanged = true;
      }
    }
    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 (modeChanged) {
        if (VOICE_MODE.equals(oldMode) && mVoiceInputWrapper != null) {
          mVoiceInputWrapper.cancel();
        }
      }
      if (modeChanged || languageChanged) {
        updateShortcutIME();
        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 {
      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();
      int version = -1;
      try {
        version = mService.getPackageManager().getPackageInfo(packageName, 0).versionCode;
      } catch (NameNotFoundException e) {
      }
      Log.w(
          TAG,
          "Unknown subtype mode: "
              + newMode
              + ","
              + version
              + ", "
              + packageName
              + ", "
              + mVoiceInputWrapper
              + ". IME is already changed to other IME.");
      if (newSubtype != null) {
        Log.w(TAG, "Subtype mode:" + newSubtype.getMode());
        Log.w(TAG, "Subtype locale:" + newSubtype.getLocale());
        Log.w(TAG, "Subtype extra value:" + newSubtype.getExtraValue());
        Log.w(TAG, "Subtype is auxiliary:" + newSubtype.isAuxiliary());
      }
    }
  }