diff options
Diffstat (limited to 'java/src')
9 files changed, 127 insertions, 76 deletions
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java index 1511dbcfe..dac12137d 100644 --- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java +++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java @@ -36,8 +36,6 @@ import java.util.TreeMap; * Various helper functions for the state database */ public class MetadataDbHelper extends SQLiteOpenHelper { - - @SuppressWarnings("unused") private static final String TAG = MetadataDbHelper.class.getSimpleName(); // This was the initial release version of the database. It should never be @@ -437,37 +435,37 @@ public class MetadataDbHelper extends SQLiteOpenHelper { */ public static ContentValues completeWithDefaultValues(final ContentValues result) throws BadFormatException { - if (!result.containsKey(WORDLISTID_COLUMN) || !result.containsKey(LOCALE_COLUMN)) { + if (null == result.get(WORDLISTID_COLUMN) || null == result.get(LOCALE_COLUMN)) { throw new BadFormatException(); } // 0 for the pending id, because there is none - if (!result.containsKey(PENDINGID_COLUMN)) result.put(PENDINGID_COLUMN, 0); + if (null == result.get(PENDINGID_COLUMN)) result.put(PENDINGID_COLUMN, 0); // This is a binary blob of a dictionary - if (!result.containsKey(TYPE_COLUMN)) result.put(TYPE_COLUMN, TYPE_BULK); + if (null == result.get(TYPE_COLUMN)) result.put(TYPE_COLUMN, TYPE_BULK); // This word list is unknown, but it's present, else we wouldn't be here, so INSTALLED - if (!result.containsKey(STATUS_COLUMN)) result.put(STATUS_COLUMN, STATUS_INSTALLED); + if (null == result.get(STATUS_COLUMN)) result.put(STATUS_COLUMN, STATUS_INSTALLED); // No description unless specified, because we can't guess it - if (!result.containsKey(DESCRIPTION_COLUMN)) result.put(DESCRIPTION_COLUMN, ""); + if (null == result.get(DESCRIPTION_COLUMN)) result.put(DESCRIPTION_COLUMN, ""); // File name - this is an asset, so it works as an already deleted file. // hence, we need to supply a non-existent file name. Anything will // do as long as it returns false when tested with File#exist(), and // the empty string does not, so it's set to "_". - if (!result.containsKey(LOCAL_FILENAME_COLUMN)) result.put(LOCAL_FILENAME_COLUMN, "_"); + if (null == result.get(LOCAL_FILENAME_COLUMN)) result.put(LOCAL_FILENAME_COLUMN, "_"); // No remote file name : this can't be downloaded. Unless specified. - if (!result.containsKey(REMOTE_FILENAME_COLUMN)) result.put(REMOTE_FILENAME_COLUMN, ""); + if (null == result.get(REMOTE_FILENAME_COLUMN)) result.put(REMOTE_FILENAME_COLUMN, ""); // 0 for the update date : 1970/1/1. Unless specified. - if (!result.containsKey(DATE_COLUMN)) result.put(DATE_COLUMN, 0); + if (null == result.get(DATE_COLUMN)) result.put(DATE_COLUMN, 0); // Checksum unknown unless specified - if (!result.containsKey(CHECKSUM_COLUMN)) result.put(CHECKSUM_COLUMN, ""); + if (null == result.get(CHECKSUM_COLUMN)) result.put(CHECKSUM_COLUMN, ""); // No filesize unless specified - if (!result.containsKey(FILESIZE_COLUMN)) result.put(FILESIZE_COLUMN, 0); + if (null == result.get(FILESIZE_COLUMN)) result.put(FILESIZE_COLUMN, 0); // Smallest possible version unless specified - if (!result.containsKey(VERSION_COLUMN)) result.put(VERSION_COLUMN, 1); + if (null == result.get(VERSION_COLUMN)) result.put(VERSION_COLUMN, 1); // Assume current format unless specified - if (!result.containsKey(FORMATVERSION_COLUMN)) + if (null == result.get(FORMATVERSION_COLUMN)) result.put(FORMATVERSION_COLUMN, UpdateHandler.MAXIMUM_SUPPORTED_FORMAT_VERSION); // No flags unless specified - if (!result.containsKey(FLAGS_COLUMN)) result.put(FLAGS_COLUMN, 0); + if (null == result.get(FLAGS_COLUMN)) result.put(FLAGS_COLUMN, 0); return result; } diff --git a/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java index df7bad8d0..9d478491a 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java +++ b/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java @@ -30,6 +30,7 @@ import com.android.inputmethod.latin.makedict.UnsupportedFormatException; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Iterator; import java.util.Locale; /** @@ -301,12 +302,14 @@ public class DictionaryInfoUtils { private static void addOrUpdateDictInfo(final ArrayList<DictionaryInfo> dictList, final DictionaryInfo newElement) { - for (final DictionaryInfo info : dictList) { - if (info.mLocale.equals(newElement.mLocale)) { - if (newElement.mVersion <= info.mVersion) { + final Iterator<DictionaryInfo> iter = dictList.iterator(); + while (iter.hasNext()) { + final DictionaryInfo thisDictInfo = iter.next(); + if (thisDictInfo.mLocale.equals(newElement.mLocale)) { + if (newElement.mVersion <= thisDictInfo.mVersion) { return; } - dictList.remove(info); + iter.remove(); } } dictList.add(newElement); diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java index 0dd302afa..94513e635 100644 --- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java +++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java @@ -54,13 +54,6 @@ public final class RichInputMethodManager { return sInstance; } - // Caveat: This may cause IPC - public static boolean isInputMethodManagerValidForUserOfThisProcess(final Context context) { - // Basically called to check whether this IME has been triggered by the current user or not - return !((InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE)). - getInputMethodList().isEmpty(); - } - public static void init(final Context context) { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); sInstance.initInternal(context, prefs); diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 9fefb58a6..a6149c6ec 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -21,6 +21,7 @@ import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.res.Resources; import android.preference.PreferenceManager; +import android.util.Log; import com.android.inputmethod.latin.LocaleUtils.RunInLocale; @@ -28,6 +29,7 @@ import java.util.HashMap; import java.util.Locale; public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener { + private static final String TAG = Settings.class.getSimpleName(); // In the same order as xml/prefs.xml public static final String PREF_GENERAL_SETTINGS = "general_settings"; public static final String PREF_AUTO_CAP = "auto_cap"; @@ -114,6 +116,12 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang @Override public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { + if (mSettingsValues == null) { + // TODO: Introduce a static function to register this class and ensure that + // loadSettings must be called before "onSharedPreferenceChanged" is called. + Log.w(TAG, "onSharedPreferenceChanged called before loadSettings."); + return; + } loadSettings(mCurrentLocale, mSettingsValues.mInputAttributes); } diff --git a/java/src/com/android/inputmethod/latin/SettingsFragment.java b/java/src/com/android/inputmethod/latin/SettingsFragment.java index 7225cd6bf..8365cce3a 100644 --- a/java/src/com/android/inputmethod/latin/SettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/SettingsFragment.java @@ -32,6 +32,7 @@ import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; +import android.util.Log; import android.view.inputmethod.InputMethodSubtype; import java.util.TreeSet; @@ -45,6 +46,7 @@ import com.android.inputmethodcommon.InputMethodSettingsFragment; public final class SettingsFragment extends InputMethodSettingsFragment implements SharedPreferences.OnSharedPreferenceChangeListener { + private static final String TAG = SettingsFragment.class.getSimpleName(); private static final boolean DBG_USE_INTERNAL_USER_DICTIONARY_SETTINGS = false; private ListPreference mVoicePreference; @@ -246,7 +248,14 @@ public final class SettingsFragment extends InputMethodSettingsFragment @Override public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { - (new BackupManager(getActivity())).dataChanged(); + final Activity activity = getActivity(); + if (activity == null) { + // TODO: Introduce a static function to register this class and ensure that + // onCreate must be called before "onSharedPreferenceChanged" is called. + Log.w(TAG, "onSharedPreferenceChanged called before activity starts."); + return; + } + (new BackupManager(activity)).dataChanged(); final Resources res = getResources(); if (key.equals(Settings.PREF_POPUP_ON)) { setPreferenceEnabled(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 282b5794f..1eca68ae5 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -43,20 +43,23 @@ public final class SubtypeSwitcher { private static final String TAG = SubtypeSwitcher.class.getSimpleName(); private static final SubtypeSwitcher sInstance = new SubtypeSwitcher(); + private /* final */ RichInputMethodManager mRichImm; private /* final */ Resources mResources; private /* final */ ConnectivityManager mConnectivityManager; - /*-----------------------------------------------------------*/ - // Variants which should be changed only by reload functions. - private NeedsToDisplayLanguage mNeedsToDisplayLanguage = new NeedsToDisplayLanguage(); + private final NeedsToDisplayLanguage mNeedsToDisplayLanguage = new NeedsToDisplayLanguage(); private InputMethodInfo mShortcutInputMethodInfo; private InputMethodSubtype mShortcutSubtype; private InputMethodSubtype mNoLanguageSubtype; - /*-----------------------------------------------------------*/ - private boolean mIsNetworkConnected; + // Dummy no language QWERTY subtype. See {@link R.xml.method}. + private static final InputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE = new InputMethodSubtype( + R.string.subtype_no_language_qwerty, R.drawable.ic_subtype_keyboard, "zz", "keyboard", + "KeyboardLayoutSet=qwerty,AsciiCapable,EnabledWhenDefaultIsNotAsciiCapable", + false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */); + static final class NeedsToDisplayLanguage { private int mEnabledSubtypeCount; private boolean mIsSystemLanguageSameAsInputLanguage; @@ -96,11 +99,6 @@ public final class SubtypeSwitcher { mRichImm = RichInputMethodManager.getInstance(); mConnectivityManager = (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE); - mNoLanguageSubtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( - 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()); @@ -255,10 +253,20 @@ public final class SubtypeSwitcher { } public InputMethodSubtype getCurrentSubtype() { - return mRichImm.getCurrentInputMethodSubtype(mNoLanguageSubtype); + return mRichImm.getCurrentInputMethodSubtype(getNoLanguageSubtype()); } public InputMethodSubtype getNoLanguageSubtype() { - return mNoLanguageSubtype; + if (mNoLanguageSubtype == null) { + mNoLanguageSubtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + SubtypeLocale.NO_LANGUAGE, SubtypeLocale.QWERTY); + } + if (mNoLanguageSubtype != null) { + return mNoLanguageSubtype; + } + Log.w(TAG, "Can't find no lanugage with QWERTY subtype"); + Log.w(TAG, "No input method subtype found; return dummy subtype: " + + DUMMY_NO_LANGUAGE_SUBTYPE); + return DUMMY_NO_LANGUAGE_SUBTYPE; } } diff --git a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java index 604ebeeb6..63d2fecd3 100644 --- a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java +++ b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java @@ -25,9 +25,9 @@ import android.content.pm.PackageManager; import android.os.Process; import android.preference.PreferenceManager; import android.util.Log; +import android.view.inputmethod.InputMethodManager; import com.android.inputmethod.compat.IntentCompatUtils; -import com.android.inputmethod.latin.RichInputMethodManager; import com.android.inputmethod.latin.Settings; /** @@ -65,17 +65,16 @@ public final class LauncherIconVisibilityManager extends BroadcastReceiver { } // The process that hosts this broadcast receiver is invoked and remains alive even after - // 1) the package has been re-installed, 2) the device has been booted, - // 3) a multiuser has been created. + // 1) the package has been re-installed, 2) the device has just booted, + // 3) a new user has been created. // There is no good reason to keep the process alive if this IME isn't a current IME. - final boolean isCurrentImeOfCurrentUser; - if (RichInputMethodManager.isInputMethodManagerValidForUserOfThisProcess(context)) { - RichInputMethodManager.init(context); - isCurrentImeOfCurrentUser = SetupActivity.isThisImeCurrent(context); - } else { - isCurrentImeOfCurrentUser = false; - } - + final InputMethodManager imm = + (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); + // Called to check whether this IME has been triggered by the current user or not + final boolean isInputMethodManagerValidForUserOfThisProcess = + !imm.getInputMethodList().isEmpty(); + final boolean isCurrentImeOfCurrentUser = isInputMethodManagerValidForUserOfThisProcess + && SetupActivity.isThisImeCurrent(context, imm); if (!isCurrentImeOfCurrentUser) { final int myPid = Process.myPid(); Log.i(TAG, "Killing my process: pid=" + myPid); diff --git a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java index 8a2de887d..a68f98fe7 100644 --- a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java +++ b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java @@ -24,8 +24,6 @@ import android.provider.Settings; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; -import com.android.inputmethod.latin.RichInputMethodManager; - public final class SetupActivity extends Activity { @Override protected void onCreate(final Bundle savedInstanceState) { @@ -40,17 +38,24 @@ public final class SetupActivity extends Activity { } } + /* + * We may not be able to get our own {@link InputMethodInfo} just after this IME is installed + * because {@link InputMethodManagerService} may not be aware of this IME yet. + * Note: {@link RichInputMethodManager} has similar methods. Here in setup wizard, we can't + * use it for the reason above. + */ + /** * Check if the IME specified by the context is enabled. - * Note that {@link RichInputMethodManager} must have been initialized before calling this - * method. + * CAVEAT: This may cause a round trip IPC. * * @param context package context of the IME to be checked. + * @param imm the {@link InputMethodManager}. * @return true if this IME is enabled. */ - public static boolean isThisImeEnabled(final Context context) { + /* package */ static boolean isThisImeEnabled(final Context context, + final InputMethodManager imm) { final String packageName = context.getPackageName(); - final InputMethodManager imm = RichInputMethodManager.getInstance().getInputMethodManager(); for (final InputMethodInfo imi : imm.getEnabledInputMethodList()) { if (packageName.equals(imi.getPackageName())) { return true; @@ -61,17 +66,36 @@ public final class SetupActivity extends Activity { /** * Check if the IME specified by the context is the current IME. - * Note that {@link RichInputMethodManager} must have been initialized before calling this - * method. + * CAVEAT: This may cause a round trip IPC. * * @param context package context of the IME to be checked. + * @param imm the {@link InputMethodManager}. * @return true if this IME is the current IME. */ - public static boolean isThisImeCurrent(final Context context) { - final InputMethodInfo myImi = - RichInputMethodManager.getInstance().getInputMethodInfoOfThisIme(); + /* package */ static boolean isThisImeCurrent(final Context context, + final InputMethodManager imm) { + final InputMethodInfo imi = getInputMethodInfoOf(context.getPackageName(), imm); final String currentImeId = Settings.Secure.getString( context.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); - return myImi.getId().equals(currentImeId); + return imi != null && imi.getId().equals(currentImeId); + } + + /** + * Get {@link InputMethodInfo} of the IME specified by the package name. + * CAVEAT: This may cause a round trip IPC. + * + * @param packageName package name of the IME. + * @param imm the {@link InputMethodManager}. + * @return the {@link InputMethodInfo} of the IME specified by the <code>packageName</code>, + * or null if not found. + */ + /* package */ static InputMethodInfo getInputMethodInfoOf(final String packageName, + final InputMethodManager imm) { + for (final InputMethodInfo imi : imm.getInputMethodList()) { + if (packageName.equals(imi.getPackageName())) { + return imi; + } + } + return null; } } diff --git a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java index 78a6478c6..13fa9d9c8 100644 --- a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java +++ b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java @@ -28,6 +28,7 @@ import android.provider.Settings; import android.util.Log; import android.view.View; import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodManager; import android.widget.ImageView; import android.widget.TextView; import android.widget.VideoView; @@ -36,7 +37,6 @@ import com.android.inputmethod.compat.TextViewCompatUtils; import com.android.inputmethod.compat.ViewCompatUtils; import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.RichInputMethodManager; import com.android.inputmethod.latin.SettingsActivity; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; @@ -48,6 +48,8 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL private static final boolean ENABLE_WELCOME_VIDEO = true; + private InputMethodManager mImm; + private View mSetupWizard; private View mWelcomeScreen; private View mSetupScreen; @@ -69,15 +71,19 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL private static final int STEP_LAUNCHING_IME_SETTINGS = 4; private static final int STEP_BACK_FROM_IME_SETTINGS = 5; - final SettingsPoolingHandler mHandler = new SettingsPoolingHandler(this); + private SettingsPoolingHandler mHandler; - static final class SettingsPoolingHandler + private static final class SettingsPoolingHandler extends StaticInnerHandlerWrapper<SetupWizardActivity> { private static final int MSG_POLLING_IME_SETTINGS = 0; private static final long IME_SETTINGS_POLLING_INTERVAL = 200; - public SettingsPoolingHandler(final SetupWizardActivity outerInstance) { + private final InputMethodManager mImmInHandler; + + public SettingsPoolingHandler(final SetupWizardActivity outerInstance, + final InputMethodManager imm) { super(outerInstance); + mImmInHandler = imm; } @Override @@ -88,7 +94,7 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL } switch (msg.what) { case MSG_POLLING_IME_SETTINGS: - if (SetupActivity.isThisImeEnabled(setupWizardActivity)) { + if (SetupActivity.isThisImeEnabled(setupWizardActivity, mImmInHandler)) { setupWizardActivity.invokeSetupWizardOfThisIme(); return; } @@ -112,11 +118,12 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL setTheme(android.R.style.Theme_Translucent_NoTitleBar); super.onCreate(savedInstanceState); + mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE); + mHandler = new SettingsPoolingHandler(this, mImm); + setContentView(R.layout.setup_wizard); mSetupWizard = findViewById(R.id.setup_wizard); - RichInputMethodManager.init(this); - if (savedInstanceState == null) { mStepNumber = determineSetupStepNumberFromLauncher(); } else { @@ -143,11 +150,12 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL R.string.setup_step1_title, R.string.setup_step1_instruction, R.string.setup_step1_finished_instruction, R.drawable.ic_setup_step1, R.string.setup_step1_action); + final SettingsPoolingHandler handler = mHandler; step1.setAction(new Runnable() { @Override public void run() { invokeLanguageAndInputSettings(); - mHandler.startPollingImeSettings(); + handler.startPollingImeSettings(); } }); mSetupStepGroup.addStep(step1); @@ -265,14 +273,15 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL void invokeInputMethodPicker() { // Invoke input method picker. - RichInputMethodManager.getInstance().getInputMethodManager() - .showInputMethodPicker(); + mImm.showInputMethodPicker(); mNeedsToAdjustStepNumberToSystemState = true; } void invokeSubtypeEnablerOfThisIme() { - final InputMethodInfo imi = - RichInputMethodManager.getInstance().getInputMethodInfoOfThisIme(); + final InputMethodInfo imi = SetupActivity.getInputMethodInfoOf(getPackageName(), mImm); + if (imi == null) { + return; + } final Intent intent = new Intent(); intent.setAction(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS); intent.addCategory(Intent.CATEGORY_DEFAULT); @@ -293,10 +302,10 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL private int determineSetupStepNumber() { mHandler.cancelPollingImeSettings(); - if (!SetupActivity.isThisImeEnabled(this)) { + if (!SetupActivity.isThisImeEnabled(this, mImm)) { return STEP_1; } - if (!SetupActivity.isThisImeCurrent(this)) { + if (!SetupActivity.isThisImeCurrent(this, mImm)) { return STEP_2; } return STEP_3; |