gt:             SharedPreferences.Editor editor = processSharedPres.edit();
context: /*
   * 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.settings.inputmethod;
  
  import com.android.settings.R;
  import com.android.settings.Settings.KeyboardLayoutPickerActivity;
  import com.android.settings.Settings.SpellCheckersSettingsActivity;
  import com.android.settings.SettingsPreferenceFragment;
  import com.android.settings.Utils;
  import com.android.settings.VoiceInputOutputSettings;
  
  import android.app.Activity;
  import android.content.ContentResolver;
  import android.content.Context;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.content.pm.PackageManager;
  import android.content.res.Configuration;
  import android.content.res.Resources;
  import android.database.ContentObserver;
  import android.hardware.input.InputManager;
  import android.hardware.input.KeyboardLayout;
  import android.os.Bundle;
  import android.os.Handler;
  import android.os.RemoteException;
  import android.preference.CheckBoxPreference;
  import android.preference.ListPreference;
  import android.preference.Preference;
  import android.preference.PreferenceCategory;
  import android.preference.PreferenceScreen;
  import android.provider.Settings;
  import android.provider.Settings.Secure;
  import android.provider.Settings.System;
  import android.text.TextUtils;
  import android.view.InputDevice;
  import android.view.inputmethod.InputMethodInfo;
  import android.view.inputmethod.InputMethodManager;
  
  import com.mediatek.common.featureoption.FeatureOption;
  import com.mediatek.common.voicecommand.IVoiceCommandManager;
  import com.mediatek.common.voicecommand.VoiceCommandListener;
  import com.mediatek.voicesettings.VoiceUiSwitchPreference;
  import com.mediatek.xlog.Xlog;
  
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  import java.util.TreeSet;
  
  public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
          implements Preference.OnPreferenceChangeListener, InputManager.InputDeviceListener,
          KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener {
  
      private static final String TAG = "InputMethodAndLanguageSettings";
      private static final String KEY_PHONE_LANGUAGE = "phone_language";
      private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method";
      private static final String KEY_INPUT_METHOD_SELECTOR = "input_method_selector";
      private static final String KEY_USER_DICTIONARY_SETTINGS = "key_user_dictionary_settings";
  
      private static final String KEY_VOICE_CATEGORY = "voice_category";
      private static final String KEY_VOICE_UI_ENABLER = "voice_ui_enabler";
  
      private static final String VOICE_CONTROL_ENABLED = "voice_control_enabled";
  
      // false: on ICS or later
      private static final boolean SHOW_INPUT_METHOD_SWITCHER_SETTINGS = false;
  
      private static final String[] sSystemSettingNames = {
          System.TEXT_AUTO_REPLACE, System.TEXT_AUTO_CAPS, System.TEXT_AUTO_PUNCTUATE,
      };
  
      private static final String[] sHardKeyboardKeys = {
          "auto_replace", "auto_caps", "auto_punctuate",
      };
  
      private int mDefaultInputMethodSelectorVisibility = 0;
      private ListPreference mShowInputMethodSelectorPref;
      private PreferenceCategory mKeyboardSettingsCategory;
      private PreferenceCategory mHardKeyboardCategory;
      private PreferenceCategory mGameControllerCategory;
      private Preference mLanguagePref;
      private final ArrayList<InputMethodPreference> mInputMethodPreferenceList =
              new ArrayList<InputMethodPreference>();
      private final ArrayList<PreferenceScreen> mHardKeyboardPreferenceList =
              new ArrayList<PreferenceScreen>();
      private InputManager mIm;
      private InputMethodManager mImm;
      private List<InputMethodInfo> mImis;
      private boolean mIsOnlyImeSettings;
      private Handler mHandler;
      @SuppressWarnings("unused")
      private SettingsObserver mSettingsObserver;
      private Intent mIntentWaitingForResult;
  
      private IVoiceCommandManager mVoiceCmdMgr;
      private VoiceCommandListener mVoiceListener;
      private PreferenceCategory mVoiceCategory;
      private VoiceUiSwitchPreference mVoiceUiEnaber;
      private boolean mVoiceControlEnable = false;
  
      //data get from locale save
      private HashMap<String, Integer> mVoiceUiAppStatus = new HashMap<String, Integer>();
      //data get from framework
      private HashMap<String, Integer> mRawData = new HashMap<String, Integer>();
  
      private class VoiceCommandCallback extends VoiceCommandListener {
          public VoiceCommandCallback(Context context) {
              super(context);
          }
  
          public void onVoiceCommandNotified(int mainAction, int subAction,Bundle extraData) {
              int result = extraData.getInt(VoiceCommandListener.ACTION_EXTRA_RESULT);
              Xlog.d(TAG, " VoiceCommandListener subAction=" + subAction + " result=" + result);
              if (subAction == VoiceCommandListener.ACTION_VOICE_SETTING_PROCESSLIST) {
                  handleVoiceUiApps(result, extraData);
              }
          }
      }
  
      private class VoiceControlListener implements VoiceUiSwitchPreference.OnCheckedChangeListener {
          @Override
          public void onCheckedChanged(boolean isChecked) {
              Xlog.d(TAG, "onCheckedChanged isChecked = " + isChecked);
              Xlog.d(TAG, "onCheckedChanged mVoiceUiEnaber = " + mVoiceUiEnaber.isChecked());
  
              Secure.putInt(getActivity().getContentResolver(),
                      VOICE_CONTROL_ENABLED, isChecked ? 1 : 0);
              boolean isAllOff = isAllDisabled(mRawData);
              Xlog.d(TAG, "isAllOff=" + isAllOff);
              if (isAllOff == !isChecked) {
                  return;
              }
  
              if (!isChecked) {
                  //pick the value is 1, and disabled them
                  for (String key : mRawData.keySet()) {
                      if (mRawData.get(key) == 1) {
                          Xlog.d(TAG, "status is unchecked, disable process name: " + key);
                          mRawData.put(key, 0);
                      }
                  }
              } else {
                  //if Voice Control is off, disabled all;
                  for (String key : mVoiceUiAppStatus.keySet()) {
                      if (mVoiceUiAppStatus.get(key) == 1) {
                          Xlog.d(TAG, "status is checked, enable process name: " + key);
                          mRawData.put(key, 1);
                      }
                  }
              }
              //if Voice Control is off/on, all;
              String[] procs = mRawData.keySet().toArray(new String[]{});
              int[] values = new int[procs.length];
              for (int i = 0; i < procs.length; i++) {
                  values[i] = mRawData.get(procs[i]);
              }
              setApps(procs, values);
              Xlog.d(TAG, "update values " + (isChecked ? "on " : "off ") + procs.toString());
  
          }
  
          @Override
          public boolean onBeforeCheckedChanged(boolean isChecked) {
              Xlog.d(TAG, "onBeforeCheckedChanged isChecked = " + isChecked);
              //judge if all is disable, if all disabed, the switch can't open.
              boolean isRemoteDataOff = isAllDisabled(mRawData);
              boolean isLocaleDataOff = isAllDisabled(mVoiceUiAppStatus);
              if (isRemoteDataOff && isLocaleDataOff) {
                  Xlog.d(TAG, "can't open switch, because all is off");
                  /**
                   * if false, handle the switch change,
                   * if true, don't handle this changed
                   */
                  return !isChecked;
              }
              return true;
          }
  
      }
  
      @Override
      public void onCreate(Bundle icicle) {
          super.onCreate(icicle);
  
          addPreferencesFromResource(R.xml.language_settings);
  
          try {
              mDefaultInputMethodSelectorVisibility = Integer.valueOf(
                      getString(R.string.input_method_selector_visibility_default_value));
          } catch (NumberFormatException e) {
          }
  
          if (getActivity().getAssets().getLocales().length == 1) {
              // No "Select language" pref if there's only one system locale available.
              getPreferenceScreen().removePreference(findPreference(KEY_PHONE_LANGUAGE));
          } else {
              mLanguagePref = findPreference(KEY_PHONE_LANGUAGE);
          }
          if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) {
              mShowInputMethodSelectorPref = (ListPreference)findPreference(
                      KEY_INPUT_METHOD_SELECTOR);
              mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this);
              // TODO: Update current input method name on summary
              updateInputMethodSelectorSummary(loadInputMethodSelectorVisibility());
          }
  
          new VoiceInputOutputSettings(this).onCreate();
  
          // Get references to dynamically constructed categories.
          mHardKeyboardCategory = (PreferenceCategory)findPreference("hard_keyboard");
          mKeyboardSettingsCategory = (PreferenceCategory)findPreference(
                  "keyboard_settings_category");
          mGameControllerCategory = (PreferenceCategory)findPreference(
                  "game_controller_settings_category");
  
          // Filter out irrelevant features if invoked from IME settings button.
          mIsOnlyImeSettings = Settings.ACTION_INPUT_METHOD_SETTINGS.equals(
                  getActivity().getIntent().getAction());
          getActivity().getIntent().setAction(null);
          if (mIsOnlyImeSettings) {
              getPreferenceScreen().removeAll();
              getPreferenceScreen().addPreference(mHardKeyboardCategory);
              if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) {
                  getPreferenceScreen().addPreference(mShowInputMethodSelectorPref);
              }
              getPreferenceScreen().addPreference(mKeyboardSettingsCategory);
          }
  
          // Build IME preference category.
          mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
          mImis = mImm.getInputMethodList();
  
          mKeyboardSettingsCategory.removeAll();
          if (!mIsOnlyImeSettings) {
              final PreferenceScreen currentIme = new PreferenceScreen(getActivity(), null);
              currentIme.setKey(KEY_CURRENT_INPUT_METHOD);
              currentIme.setTitle(getResources().getString(R.string.current_input_method));
              mKeyboardSettingsCategory.addPreference(currentIme);
          }
  
          mInputMethodPreferenceList.clear();
          final int N = (mImis == null ? 0 : mImis.size());
          for (int i = 0; i < N; ++i) {
              final InputMethodInfo imi = mImis.get(i);
              final InputMethodPreference pref = getInputMethodPreference(imi, N);
              mInputMethodPreferenceList.add(pref);
          }
  
          if (!mInputMethodPreferenceList.isEmpty()) {
              Collections.sort(mInputMethodPreferenceList);
              for (int i = 0; i < N; ++i) {
                  mKeyboardSettingsCategory.addPreference(mInputMethodPreferenceList.get(i));
              }
          }
  
          // Build hard keyboard and game controller preference categories.
          mIm = (InputManager)getActivity().getSystemService(Context.INPUT_SERVICE);
          updateInputDevices();
  
          // Spell Checker
          final Intent intent = new Intent(Intent.ACTION_MAIN);
          intent.setClass(getActivity(), SpellCheckersSettingsActivity.class);
          final SpellCheckersPreference scp = ((SpellCheckersPreference)findPreference(
                  "spellcheckers_settings"));
          if (scp != null) {
              scp.setFragmentIntent(this, intent);
          }
  
          mHandler = new Handler();
          mSettingsObserver = new SettingsObserver(mHandler, getActivity());
  
          //For voice control, these should be changed according process name changed.
          //For voice control
          mVoiceCategory = (PreferenceCategory)findPreference(KEY_VOICE_CATEGORY);
          if (mVoiceCategory != null) {
              mVoiceUiEnaber = (VoiceUiSwitchPreference)mVoiceCategory.findPreference(KEY_VOICE_UI_ENABLER);
          }
  
          if (!mIsOnlyImeSettings && FeatureOption.MTK_VOICE_UI_SUPPORT) {
              mVoiceUiAppStatus.put("com.android.phone", 1);
              mVoiceUiAppStatus.put("com.android.deskclock", 1);
              mVoiceUiAppStatus.put("com.android.gallery3d", 1);
              mVoiceUiAppStatus.put("com.android.music", 1);
              
              if (mVoiceUiEnaber != null) {
                  mVoiceUiEnaber.setOnCheckedChangeListener(new VoiceControlListener());
              }
  
              mVoiceCmdMgr = (IVoiceCommandManager)getSystemService("voicecommand");
              if (mVoiceCmdMgr != null) {
                  mVoiceListener = new VoiceCommandCallback(getActivity());
              }
          } else {
              Xlog.d(TAG, "going to remove voice ui feature ");
              if (mVoiceUiEnaber != null && mVoiceCategory != null) {
                  Xlog.d(TAG, "removed done");
                  mVoiceCategory.removePreference(mVoiceUiEnaber);
              }
          }
      }
  
      private void updateInputMethodSelectorSummary(int value) {
          String[] inputMethodSelectorTitles = getResources().getStringArray(
                  R.array.input_method_selector_titles);
          if (inputMethodSelectorTitles.length > value) {
              mShowInputMethodSelectorPref.setSummary(inputMethodSelectorTitles[value]);
              mShowInputMethodSelectorPref.setValue(String.valueOf(value));
          }
      }
  
      private void updateUserDictionaryPreference(Preference userDictionaryPreference) {
          final Activity activity = getActivity();
          final TreeSet<String> localeList = UserDictionaryList.getUserDictionaryLocalesSet(activity);
          if (null == localeList) {
              // The locale list is null if and only if the user dictionary service is
              // not present or disabled. In this case we need to remove the preference.
              getPreferenceScreen().removePreference(userDictionaryPreference);
          } else if (localeList.size() <= 1) {
              final Intent intent =
                      new Intent(UserDictionaryList.USER_DICTIONARY_SETTINGS_INTENT_ACTION);
              userDictionaryPreference.setTitle(R.string.user_dict_single_settings_title);
              userDictionaryPreference.setIntent(intent);
              userDictionaryPreference.setFragment(
                      com.android.settings.UserDictionarySettings.class.getName());
              // If the size of localeList is 0, we don't set the locale parameter in the
              // extras. This will be interpreted by the UserDictionarySettings class as
              // meaning "the current locale".
              // Note that with the current code for UserDictionaryList#getUserDictionaryLocalesSet()
              // the locale list always has at least one element, since it always includes the current
              // locale explicitly. @see UserDictionaryList.getUserDictionaryLocalesSet().
              if (localeList.size() == 1) {
                  final String locale = (String)localeList.toArray()[0];
                  userDictionaryPreference.getExtras().putString("locale", locale);
              }
          } else {
              userDictionaryPreference.setTitle(R.string.user_dict_multiple_settings_title);
              userDictionaryPreference.setFragment(UserDictionaryList.class.getName());
          }
      }
  
      @Override
      public void onResume() {
          super.onResume();
  
          mSettingsObserver.resume();
          mIm.registerInputDeviceListener(this, null);
  
          if (!mIsOnlyImeSettings) {
              if (mLanguagePref != null) {
                  Configuration conf = getResources().getConfiguration();
                  String language = conf.locale.getLanguage();
                  String localeString;
                  // TODO: This is not an accurate way to display the locale, as it is
                  // just working around the fact that we support limited dialects
                  // and want to pretend that the language is valid for all locales.
                  // We need a way to support languages that aren't tied to a particular
                  // locale instead of hiding the locale qualifier.
                  if (hasOnlyOneLanguageInstance(language,
                          Resources.getSystem().getAssets().getLocales())) {
                      localeString = conf.locale.getDisplayLanguage(conf.locale);
                  } else {
                      localeString = conf.locale.getDisplayName(conf.locale);
                  }
                  if (localeString.length() > 1) {
                      localeString = Character.toUpperCase(localeString.charAt(0))
                              + localeString.substring(1);
                      mLanguagePref.setSummary(localeString);
                  }
              }
  
              updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_SETTINGS));
              if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) {
                  mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this);
              }
          }
  
          // Hard keyboard
          if (!mHardKeyboardPreferenceList.isEmpty()) {
              for (int i = 0; i < sHardKeyboardKeys.length; ++i) {
                  CheckBoxPreference chkPref = (CheckBoxPreference)
                          mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i]);
                  chkPref.setChecked(
                          System.getInt(getContentResolver(), sSystemSettingNames[i], 1) > 0);
              }
          }
  
          updateInputDevices();
  
          // IME
          InputMethodAndSubtypeUtil.loadInputMethodSubtypeList(
                  this, getContentResolver(), mImis, null);
          updateActiveInputMethodsSummary();
  
          //Voice control
          if (!mIsOnlyImeSettings && FeatureOption.MTK_VOICE_UI_SUPPORT) {
              SharedPreferences processSharedPres = getActivity().getSharedPreferences(
                      "voice_ui_settings", Context.MODE_PRIVATE);
              for (String key : mVoiceUiAppStatus.keySet()) {
                  int state = processSharedPres.getInt(key, 1);
                  mVoiceUiAppStatus.put(key, state);
              }
              Xlog.d(TAG, "read from shared preference " + mVoiceUiAppStatus.toString());
  
              mVoiceControlEnable = (Secure.getInt(getContentResolver(), VOICE_CONTROL_ENABLED, 0) == 1);
              Xlog.d(TAG, "Voice Control is " + (mVoiceControlEnable ? "on" : "off"));
              mVoiceUiEnaber.setChecked(mVoiceControlEnable, false);
  
              if (mVoiceCmdMgr != null) {
                  try {
                      Xlog.d(TAG, "register voice command listener");
                      mVoiceCmdMgr.registerListener(mVoiceListener);
                      Xlog.d(TAG, "send command mainAction = " + VoiceCommandListener.ACTION_MAIN_VOICE_SETTING 
                              + " subAction = " + VoiceCommandListener.ACTION_VOICE_SETTING_PROCESSLIST);
                      mVoiceCmdMgr.sendCommand(getActivity(),
                              VoiceCommandListener.ACTION_MAIN_VOICE_SETTING,
                              VoiceCommandListener.ACTION_VOICE_SETTING_PROCESSLIST,null);
                  } catch (RemoteException e) {
                      Xlog.w(TAG, "Remote exception error" + e.getMessage());
                      e.printStackTrace();
                  } catch (IllegalAccessException e) {
                      Xlog.w(TAG, "IllegalAccessException exception error" + e.getMessage());
                      e.printStackTrace();
                  }
              }
          }
      }
  
      @Override
      public void onPause() {
          super.onPause();
  
          mIm.unregisterInputDeviceListener(this);
          mSettingsObserver.pause();
  
          if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) {
              mShowInputMethodSelectorPref.setOnPreferenceChangeListener(null);
          }
          InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
                  this, getContentResolver(), mImis, !mHardKeyboardPreferenceList.isEmpty());
  
          //Voice control
          if (!mIsOnlyImeSettings && FeatureOption.MTK_VOICE_UI_SUPPORT) {
              if (mVoiceCmdMgr != null) {
                  try{
                      mVoiceCmdMgr.unRegisterListener(mVoiceListener);
                  } catch (RemoteException e) {
                      Xlog.w(TAG, "Remote exception error" + e.getMessage());
                      e.printStackTrace();
                  } catch (IllegalAccessException e) {
                      Xlog.w(TAG, "IllegalAccessException exception error" + e.getMessage());
                      e.printStackTrace();
                  }
              }
          }
  
          if (!mIsOnlyImeSettings && FeatureOption.MTK_VOICE_UI_SUPPORT) {
              SharedPreferences processSharedPres = getActivity().getSharedPreferences(
                      "voice_ui_settings", Context.MODE_PRIVATE);
  