diff options
Diffstat (limited to 'java/src')
41 files changed, 1396 insertions, 676 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java index 442ab3e3a..31e142e72 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java @@ -21,7 +21,7 @@ import android.media.AudioManager; import android.os.Build; import android.os.SystemClock; import android.provider.Settings; -import android.support.v4.view.accessibility.AccessibilityEventCompat; +import androidx.core.view.accessibility.AccessibilityEventCompat; import android.text.TextUtils; import android.util.Log; import android.view.MotionEvent; diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java index 237117d10..f7a11639d 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java +++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java @@ -18,9 +18,9 @@ package com.android.inputmethod.accessibility; import android.content.Context; import android.os.SystemClock; -import android.support.v4.view.AccessibilityDelegateCompat; -import android.support.v4.view.ViewCompat; -import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import android.util.Log; import android.view.MotionEvent; import android.view.View; diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java index 2de71cec9..a3511c63f 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java +++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java @@ -18,11 +18,11 @@ package com.android.inputmethod.accessibility; import android.graphics.Rect; import android.os.Bundle; -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 androidx.core.view.ViewCompat; +import androidx.core.view.accessibility.AccessibilityEventCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; +import androidx.core.view.accessibility.AccessibilityNodeProviderCompat; +import androidx.core.view.accessibility.AccessibilityRecordCompat; import android.util.Log; import android.view.View; import android.view.accessibility.AccessibilityEvent; diff --git a/java/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java b/java/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java new file mode 100644 index 000000000..f5e56eb4b --- /dev/null +++ b/java/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013 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.inputmethod.compat; + +import android.content.pm.PackageInfo; + +@SuppressWarnings("unused") +public class AppWorkaroundsHelper { + private AppWorkaroundsHelper() { + // This helper class is not publicly instantiable. + } + + public static boolean evaluateIsBrokenByRecorrection(final PackageInfo info) { + return false; + } +} diff --git a/java/src/com/android/inputmethod/compat/UserManagerCompatUtils.java b/java/src/com/android/inputmethod/compat/UserManagerCompatUtils.java index 5dee31629..a0ca2c9f2 100644 --- a/java/src/com/android/inputmethod/compat/UserManagerCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/UserManagerCompatUtils.java @@ -19,7 +19,7 @@ package com.android.inputmethod.compat; import android.content.Context; import android.os.Build; import android.os.UserManager; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.reflect.Method; diff --git a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java index 16260ab6a..a584625e2 100644 --- a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java @@ -20,7 +20,7 @@ import android.view.View; import java.lang.reflect.Method; -// TODO: Use {@link android.support.v4.view.ViewCompat} instead of this utility class. +// TODO: Use {@link androidx.core.view.ViewCompat} instead of this utility class. // Currently {@link #getPaddingEnd(View)} and {@link #setPaddingRelative(View,int,int,int,int)} // are missing from android-support-v4 static library in KitKat SDK. public final class ViewCompatUtils { diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java new file mode 100644 index 000000000..13caea403 --- /dev/null +++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2013 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.inputmethod.dictionarypack; + +/** + * A class to group constants for dictionary pack usage. + * + * This class only defines constants. It should not make any references to outside code as far as + * possible, as it's used to separate cleanly the keyboard code from the dictionary pack code; this + * is needed in particular to cleanly compile regression tests. + */ +public class DictionaryPackConstants { + /** + * The root domain for the dictionary pack, upon which authorities and actions will append + * their own distinctive strings. + */ + private static final String DICTIONARY_DOMAIN = "com.android.inputmethod.dictionarypack.aosp"; + + /** + * Authority for the ContentProvider protocol. + */ + // TODO: find some way to factorize this string with the one in the resources + public static final String AUTHORITY = DICTIONARY_DOMAIN; + + /** + * The action of the intent for publishing that new dictionary data is available. + */ + // TODO: make this different across different packages. A suggested course of action is + // to use the package name inside this string. + // NOTE: The appended string should be uppercase like all other actions, but it's not for + // historical reasons. + public static final String NEW_DICTIONARY_INTENT_ACTION = DICTIONARY_DOMAIN + ".newdict"; + + /** + * The action of the intent sent by the dictionary pack to ask for a client to make + * itself known. This is used when the settings activity is brought up for a client the + * dictionary pack does not know about. + */ + public static final String UNKNOWN_DICTIONARY_PROVIDER_CLIENT = DICTIONARY_DOMAIN + + ".UNKNOWN_CLIENT"; + + // In the above intents, the name of the string extra that contains the name of the client + // we want information about. + public static final String DICTIONARY_PROVIDER_CLIENT_EXTRA = "client"; + + /** + * The action of the intent to tell the dictionary provider to update now. + */ + public static final String UPDATE_NOW_INTENT_ACTION = DICTIONARY_DOMAIN + + ".UPDATE_NOW"; + + /** + * The intent action to inform the dictionary provider to initialize the db + * and update now. + */ + public static final String INIT_AND_UPDATE_NOW_INTENT_ACTION = DICTIONARY_DOMAIN + + ".INIT_AND_UPDATE_NOW"; +} diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java b/java/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java new file mode 100644 index 000000000..512d426aa --- /dev/null +++ b/java/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2013 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.inputmethod.dictionarypack; + +import android.content.Context; + +/** + * Helper to get the metadata URI from its base URI. + */ +@SuppressWarnings("unused") +public class MetadataUriGetter { + public static String getUri(final Context context, final String baseUri) { + return baseUri; + } +} diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java index 582e09124..797541a15 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiLayoutParams.java @@ -17,7 +17,7 @@ package com.android.inputmethod.keyboard.emoji; import android.content.res.Resources; -import android.support.v4.view.ViewPager; +import androidx.viewpager.widget.ViewPager; import android.view.View; import android.widget.LinearLayout; diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesAdapter.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesAdapter.java index 68056e0eb..18b9c7e36 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesAdapter.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesAdapter.java @@ -16,7 +16,7 @@ package com.android.inputmethod.keyboard.emoji; -import android.support.v4.view.PagerAdapter; +import androidx.viewpager.widget.PagerAdapter; import android.util.Log; import android.util.SparseArray; import android.view.LayoutInflater; diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java index a3b869d73..9ba8d2ba2 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java @@ -23,7 +23,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Color; import android.preference.PreferenceManager; -import android.support.v4.view.ViewPager; +import androidx.viewpager.widget.ViewPager; import android.util.AttributeSet; import android.util.Pair; import android.util.TypedValue; diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorProvider.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorProvider.java new file mode 100644 index 000000000..a48b41fa7 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorProvider.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2013 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.inputmethod.latin; + +/** + * Factory for instantiating DictionaryFacilitator objects. + */ +public class DictionaryFacilitatorProvider { + public static DictionaryFacilitator getDictionaryFacilitator(boolean isNeededForSpellChecking) { + return new DictionaryFacilitatorImpl(); + } +} diff --git a/java/src/com/android/inputmethod/latin/PersonalDictionaryLookup.java b/java/src/com/android/inputmethod/latin/PersonalDictionaryLookup.java deleted file mode 100644 index eed4ec1a0..000000000 --- a/java/src/com/android/inputmethod/latin/PersonalDictionaryLookup.java +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Copyright (C) 2015 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.inputmethod.latin; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.ContentObserver; -import android.database.Cursor; -import android.net.Uri; -import android.provider.UserDictionary; -import android.text.TextUtils; -import android.util.Log; - -import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.common.CollectionUtils; -import com.android.inputmethod.latin.common.LocaleUtils; -import com.android.inputmethod.latin.define.DebugFlags; -import com.android.inputmethod.latin.utils.ExecutorUtils; - -import java.io.Closeable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * This class provides the ability to look into the system-wide "Personal dictionary". It loads the - * data once when created and reloads it when notified of changes to {@link UserDictionary} - * - * It can be used directly to validate words or expand shortcuts, and it can be used by instances - * of {@link PersonalLanguageModelHelper} that create language model files for a specific input - * locale. - * - * Note, that the initial dictionary loading happens asynchronously so it is possible (hopefully - * rarely) that {@link #isValidWord} or {@link #expandShortcut} is called before the initial load - * has started. - * - * The caller should explicitly call {@link #close} when the object is no longer needed, in order - * to release any resources and references to this object. A service should create this object in - * {@link android.app.Service#onCreate} and close it in {@link android.app.Service#onDestroy}. - */ -public class PersonalDictionaryLookup implements Closeable { - - /** - * To avoid loading too many dictionary entries in memory, we cap them at this number. If - * that number is exceeded, the lowest-frequency items will be dropped. Note, there is no - * explicit cap on the number of locales in every entry. - */ - private static final int MAX_NUM_ENTRIES = 1000; - - /** - * The delay (in milliseconds) to impose on reloads. Previously scheduled reloads will be - * cancelled if a new reload is scheduled before the delay expires. Thus, only the last - * reload in the series of frequent reloads will execute. - * - * Note, this value should be low enough to allow the "Add to dictionary" feature in the - * TextView correction (red underline) drop-down menu to work properly in the following case: - * - * 1. User types OOV (out-of-vocabulary) word. - * 2. The OOV is red-underlined. - * 3. User selects "Add to dictionary". The red underline disappears while the OOV is - * in a composing span. - * 4. The user taps space. The red underline should NOT reappear. If this value is very - * high and the user performs the space tap fast enough, the red underline may reappear. - */ - @UsedForTesting - static final int RELOAD_DELAY_MS = 200; - - @UsedForTesting - static final Locale ANY_LOCALE = new Locale(""); - - private final String mTag; - private final ContentResolver mResolver; - private final String mServiceName; - - /** - * Interface to implement for classes interested in getting notified of updates. - */ - public static interface PersonalDictionaryListener { - public void onUpdate(); - } - - private final Set<PersonalDictionaryListener> mListeners = new HashSet<>(); - - public void addListener(@Nonnull final PersonalDictionaryListener listener) { - mListeners.add(listener); - } - - public void removeListener(@Nonnull final PersonalDictionaryListener listener) { - mListeners.remove(listener); - } - - /** - * Broadcast the update to all the Locale-specific language models. - */ - @UsedForTesting - void notifyListeners() { - for (PersonalDictionaryListener listener : mListeners) { - listener.onUpdate(); - } - } - - /** - * Content observer for changes to the personal dictionary. It has the following properties: - * 1. It spawns off a reload in another thread, after some delay. - * 2. It cancels previously scheduled reloads, and only executes the latest. - * 3. It may be called multiple times quickly in succession (and is in fact called so - * when the dictionary is edited through its settings UI, when sometimes multiple - * notifications are sent for the edited entry, but also for the entire dictionary). - */ - private class PersonalDictionaryContentObserver extends ContentObserver implements Runnable { - public PersonalDictionaryContentObserver() { - super(null); - } - - @Override - public boolean deliverSelfNotifications() { - return true; - } - - // Support pre-API16 platforms. - @Override - public void onChange(boolean selfChange) { - onChange(selfChange, null); - } - - @Override - public void onChange(boolean selfChange, Uri uri) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "onChange() : URI = " + uri); - } - // Cancel (but don't interrupt) any pending reloads (except the initial load). - if (mReloadFuture != null && !mReloadFuture.isCancelled() && - !mReloadFuture.isDone()) { - // Note, that if already cancelled or done, this will do nothing. - boolean isCancelled = mReloadFuture.cancel(false); - if (DebugFlags.DEBUG_ENABLED) { - if (isCancelled) { - Log.d(mTag, "onChange() : Canceled previous reload request"); - } else { - Log.d(mTag, "onChange() : Failed to cancel previous reload request"); - } - } - } - - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "onChange() : Scheduling reload in " + RELOAD_DELAY_MS + " ms"); - } - - // Schedule a new reload after RELOAD_DELAY_MS. - mReloadFuture = ExecutorUtils.getBackgroundExecutor(mServiceName) - .schedule(this, RELOAD_DELAY_MS, TimeUnit.MILLISECONDS); - } - - @Override - public void run() { - loadPersonalDictionary(); - } - } - - private final PersonalDictionaryContentObserver mPersonalDictionaryContentObserver = - new PersonalDictionaryContentObserver(); - - /** - * Indicates that a load is in progress, so no need for another. - */ - private AtomicBoolean mIsLoading = new AtomicBoolean(false); - - /** - * Indicates that this lookup object has been close()d. - */ - private AtomicBoolean mIsClosed = new AtomicBoolean(false); - - /** - * We store a map from a dictionary word to the set of locales & raw string(as it appears) - * We then iterate over the set of locales to find a match using LocaleUtils. - */ - private volatile HashMap<String, HashMap<Locale, String>> mDictWords; - - /** - * We store a map from a shortcut to a word for each locale. - * Shortcuts that apply to any locale are keyed by {@link #ANY_LOCALE}. - */ - private volatile HashMap<Locale, HashMap<String, String>> mShortcutsPerLocale; - - /** - * The last-scheduled reload future. Saved in order to cancel a pending reload if a new one - * is coming. - */ - private volatile ScheduledFuture<?> mReloadFuture; - - private volatile List<DictionaryStats> mDictionaryStats; - - /** - * @param context the context from which to obtain content resolver - */ - public PersonalDictionaryLookup( - @Nonnull final Context context, - @Nonnull final String serviceName) { - mTag = serviceName + ".Personal"; - - Log.i(mTag, "create()"); - - mServiceName = serviceName; - mDictionaryStats = new ArrayList<DictionaryStats>(); - mDictionaryStats.add(new DictionaryStats(ANY_LOCALE, Dictionary.TYPE_USER, 0)); - mDictionaryStats.add(new DictionaryStats(ANY_LOCALE, Dictionary.TYPE_USER_SHORTCUT, 0)); - - // Obtain a content resolver. - mResolver = context.getContentResolver(); - } - - public List<DictionaryStats> getDictionaryStats() { - return mDictionaryStats; - } - - public void open() { - Log.i(mTag, "open()"); - - // Schedule the initial load to run immediately. It's possible that the first call to - // isValidWord occurs before the dictionary has actually loaded, so it should not - // assume that the dictionary has been loaded. - loadPersonalDictionary(); - - // Register the observer to be notified on changes to the personal dictionary and all - // individual items. - // - // If the user is interacting with the Personal Dictionary settings UI, or with the - // "Add to dictionary" drop-down option, duplicate notifications will be sent for the same - // edit: if a new entry is added, there is a notification for the entry itself, and - // separately for the entire dictionary. However, when used programmatically, - // only notifications for the specific edits are sent. Thus, the observer is registered to - // receive every possible notification, and instead has throttling logic to avoid doing too - // many reloads. - mResolver.registerContentObserver( - UserDictionary.Words.CONTENT_URI, - true /* notifyForDescendents */, - mPersonalDictionaryContentObserver); - } - - /** - * To be called by the garbage collector in the off chance that the service did not clean up - * properly. Do not rely on this getting called, and make sure close() is called explicitly. - */ - @Override - public void finalize() throws Throwable { - try { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "finalize()"); - } - close(); - } finally { - super.finalize(); - } - } - - /** - * Cleans up PersonalDictionaryLookup: shuts down any extra threads and unregisters the observer. - * - * It is safe, but not advised to call this multiple times, and isValidWord would continue to - * work, but no data will be reloaded any longer. - */ - @Override - public void close() { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "close() : Unregistering content observer"); - } - if (mIsClosed.compareAndSet(false, true)) { - // Unregister the content observer. - mResolver.unregisterContentObserver(mPersonalDictionaryContentObserver); - } - } - - /** - * Returns true if the initial load has been performed. - * - * @return true if the initial load is successful - */ - public boolean isLoaded() { - return mDictWords != null && mShortcutsPerLocale != null; - } - - /** - * Returns the set of words defined for the given locale and more general locales. - * - * For example, input locale en_US uses data for en_US, en, and the global dictionary. - * - * Note that this method returns expanded words, not shortcuts. Shortcuts are handled - * by {@link #getShortcutsForLocale}. - * - * @param inputLocale the locale to restrict for - * @return set of words that apply to the given locale. - */ - public Set<String> getWordsForLocale(@Nonnull final Locale inputLocale) { - final HashMap<String, HashMap<Locale, String>> dictWords = mDictWords; - if (CollectionUtils.isNullOrEmpty(dictWords)) { - return Collections.emptySet(); - } - - final Set<String> words = new HashSet<>(); - final String inputLocaleString = inputLocale.toString(); - for (String word : dictWords.keySet()) { - HashMap<Locale, String> localeStringMap = dictWords.get(word); - if (!CollectionUtils.isNullOrEmpty(localeStringMap)) { - for (Locale wordLocale : localeStringMap.keySet()) { - final String wordLocaleString = wordLocale.toString(); - final int match = LocaleUtils.getMatchLevel(wordLocaleString, inputLocaleString); - if (LocaleUtils.isMatch(match)) { - words.add(localeStringMap.get(wordLocale)); - } - } - } - } - return words; - } - - /** - * Returns the set of shortcuts defined for the given locale and more general locales. - * - * For example, input locale en_US uses data for en_US, en, and the global dictionary. - * - * Note that this method returns shortcut keys, not expanded words. Words are handled - * by {@link #getWordsForLocale}. - * - * @param inputLocale the locale to restrict for - * @return set of shortcuts that apply to the given locale. - */ - public Set<String> getShortcutsForLocale(@Nonnull final Locale inputLocale) { - final Map<Locale, HashMap<String, String>> shortcutsPerLocale = mShortcutsPerLocale; - if (CollectionUtils.isNullOrEmpty(shortcutsPerLocale)) { - return Collections.emptySet(); - } - - final Set<String> shortcuts = new HashSet<>(); - if (!TextUtils.isEmpty(inputLocale.getCountry())) { - // First look for the country-specific shortcut: en_US, en_UK, fr_FR, etc. - final Map<String, String> countryShortcuts = shortcutsPerLocale.get(inputLocale); - if (!CollectionUtils.isNullOrEmpty(countryShortcuts)) { - shortcuts.addAll(countryShortcuts.keySet()); - } - } - - // Next look for the language-specific shortcut: en, fr, etc. - final Locale languageOnlyLocale = - LocaleUtils.constructLocaleFromString(inputLocale.getLanguage()); - final Map<String, String> languageShortcuts = shortcutsPerLocale.get(languageOnlyLocale); - if (!CollectionUtils.isNullOrEmpty(languageShortcuts)) { - shortcuts.addAll(languageShortcuts.keySet()); - } - - // If all else fails, look for a global shortcut. - final Map<String, String> globalShortcuts = shortcutsPerLocale.get(ANY_LOCALE); - if (!CollectionUtils.isNullOrEmpty(globalShortcuts)) { - shortcuts.addAll(globalShortcuts.keySet()); - } - - return shortcuts; - } - - /** - * Determines if the given word is a valid word in the given locale based on the dictionary. - * It tries hard to find a match: for example, casing is ignored and if the word is present in a - * more general locale (e.g. en or all locales), and isValidWord is asking for a more specific - * locale (e.g. en_US), it will be considered a match. - * - * @param word the word to match - * @param inputLocale the locale in which to match the word - * @return true iff the word has been matched for this locale in the dictionary. - */ - public boolean isValidWord(@Nonnull final String word, @Nonnull final Locale inputLocale) { - if (!isLoaded()) { - // This is a corner case in the event the initial load of the dictionary has not - // completed. In that case, we assume the word is not a valid word in the dictionary. - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "isValidWord() : Initial load not complete"); - } - return false; - } - - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "isValidWord() : Word [" + word + "] in Locale [" + inputLocale + "]"); - } - // Atomically obtain the current copy of mDictWords; - final HashMap<String, HashMap<Locale, String>> dictWords = mDictWords; - // Lowercase the word using the given locale. Note, that dictionary - // words are lowercased using their locale, and theoretically the - // lowercasing between two matching locales may differ. For simplicity - // we ignore that possibility. - final String lowercased = word.toLowerCase(inputLocale); - final HashMap<Locale, String> dictLocales = dictWords.get(lowercased); - - if (CollectionUtils.isNullOrEmpty(dictLocales)) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "isValidWord() : No entry for word [" + word + "]"); - } - return false; - } else { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "isValidWord() : Found entry for word [" + word + "]"); - } - // Iterate over the locales this word is in. - for (final Locale dictLocale : dictLocales.keySet()) { - final int matchLevel = LocaleUtils.getMatchLevel(dictLocale.toString(), - inputLocale.toString()); - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "isValidWord() : MatchLevel for DictLocale [" + dictLocale - + "] and InputLocale [" + inputLocale + "] is " + matchLevel); - } - if (LocaleUtils.isMatch(matchLevel)) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "isValidWord() : MatchLevel " + matchLevel + " IS a match"); - } - return true; - } - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "isValidWord() : MatchLevel " + matchLevel + " is NOT a match"); - } - } - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "isValidWord() : False, since none of the locales matched"); - } - return false; - } - } - - /** - * Expands the given shortcut for the given locale. - * - * @param shortcut the shortcut to expand - * @param inputLocale the locale in which to expand the shortcut - * @return expanded shortcut iff the word is a shortcut in the dictionary. - */ - @Nullable public String expandShortcut( - @Nonnull final String shortcut, @Nonnull final Locale inputLocale) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "expandShortcut() : Shortcut [" + shortcut + "] for [" + inputLocale + "]"); - } - - // Atomically obtain the current copy of mShortcuts; - final HashMap<Locale, HashMap<String, String>> shortcutsPerLocale = mShortcutsPerLocale; - - // Exit as early as possible. Most users don't use shortcuts. - if (CollectionUtils.isNullOrEmpty(shortcutsPerLocale)) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "expandShortcut() : User has no shortcuts"); - } - return null; - } - - if (!TextUtils.isEmpty(inputLocale.getCountry())) { - // First look for the country-specific shortcut: en_US, en_UK, fr_FR, etc. - final String expansionForCountry = expandShortcut( - shortcutsPerLocale, shortcut, inputLocale); - if (!TextUtils.isEmpty(expansionForCountry)) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "expandShortcut() : Country expansion is [" - + expansionForCountry + "]"); - } - return expansionForCountry; - } - } - - // Next look for the language-specific shortcut: en, fr, etc. - final Locale languageOnlyLocale = - LocaleUtils.constructLocaleFromString(inputLocale.getLanguage()); - final String expansionForLanguage = expandShortcut( - shortcutsPerLocale, shortcut, languageOnlyLocale); - if (!TextUtils.isEmpty(expansionForLanguage)) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "expandShortcut() : Language expansion is [" - + expansionForLanguage + "]"); - } - return expansionForLanguage; - } - - // If all else fails, look for a global shortcut. - final String expansionForGlobal = expandShortcut(shortcutsPerLocale, shortcut, ANY_LOCALE); - if (!TextUtils.isEmpty(expansionForGlobal) && DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "expandShortcut() : Global expansion is [" + expansionForGlobal + "]"); - } - return expansionForGlobal; - } - - @Nullable private String expandShortcut( - @Nullable final HashMap<Locale, HashMap<String, String>> shortcutsPerLocale, - @Nonnull final String shortcut, - @Nonnull final Locale locale) { - if (CollectionUtils.isNullOrEmpty(shortcutsPerLocale)) { - return null; - } - final HashMap<String, String> localeShortcuts = shortcutsPerLocale.get(locale); - if (CollectionUtils.isNullOrEmpty(localeShortcuts)) { - return null; - } - return localeShortcuts.get(shortcut); - } - - /** - * Loads the personal dictionary in the current thread. - * - * Only one reload can happen at a time. If already running, will exit quickly. - */ - private void loadPersonalDictionary() { - // Bail out if already in the process of loading. - if (!mIsLoading.compareAndSet(false, true)) { - Log.i(mTag, "loadPersonalDictionary() : Already Loading (exit)"); - return; - } - Log.i(mTag, "loadPersonalDictionary() : Start Loading"); - HashMap<String, HashMap<Locale, String>> dictWords = new HashMap<>(); - HashMap<Locale, HashMap<String, String>> shortcutsPerLocale = new HashMap<>(); - // Load the dictionary. Items are returned in the default sort order (by frequency). - Cursor cursor = mResolver.query(UserDictionary.Words.CONTENT_URI, - null, null, null, UserDictionary.Words.DEFAULT_SORT_ORDER); - if (null == cursor || cursor.getCount() < 1) { - Log.i(mTag, "loadPersonalDictionary() : Empty"); - } else { - // Iterate over the entries in the personal dictionary. Note, that iteration is in - // descending frequency by default. - while (dictWords.size() < MAX_NUM_ENTRIES && cursor.moveToNext()) { - // If there is no column for locale, skip this entry. An empty - // locale on the other hand will not be skipped. - final int dictLocaleIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE); - if (dictLocaleIndex < 0) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "loadPersonalDictionary() : Entry without LOCALE, skipping"); - } - continue; - } - // If there is no column for word, skip this entry. - final int dictWordIndex = cursor.getColumnIndex(UserDictionary.Words.WORD); - if (dictWordIndex < 0) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "loadPersonalDictionary() : Entry without WORD, skipping"); - } - continue; - } - // If the word is null, skip this entry. - final String rawDictWord = cursor.getString(dictWordIndex); - if (null == rawDictWord) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "loadPersonalDictionary() : Null word"); - } - continue; - } - // If the locale is null, that's interpreted to mean all locales. Note, the special - // zz locale for an Alphabet (QWERTY) layout will not match any actual language. - String localeString = cursor.getString(dictLocaleIndex); - if (null == localeString) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "loadPersonalDictionary() : Null locale for word [" + - rawDictWord + "], assuming all locales"); - } - // For purposes of LocaleUtils, an empty locale matches everything. - localeString = ""; - } - final Locale dictLocale = LocaleUtils.constructLocaleFromString(localeString); - // Lowercase the word before storing it. - final String dictWord = rawDictWord.toLowerCase(dictLocale); - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "loadPersonalDictionary() : Adding word [" + dictWord - + "] for locale " + dictLocale + "with value" + rawDictWord); - } - // Check if there is an existing entry for this word. - HashMap<Locale, String> dictLocales = dictWords.get(dictWord); - if (CollectionUtils.isNullOrEmpty(dictLocales)) { - // If there is no entry for this word, create one. - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "loadPersonalDictionary() : Word [" + dictWord + - "] not seen for other locales, creating new entry"); - } - dictLocales = new HashMap<>(); - dictWords.put(dictWord, dictLocales); - } - // Append the locale to the list of locales this word is in. - dictLocales.put(dictLocale, rawDictWord); - - // If there is no column for a shortcut, we're done. - final int shortcutIndex = cursor.getColumnIndex(UserDictionary.Words.SHORTCUT); - if (shortcutIndex < 0) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "loadPersonalDictionary() : Entry without SHORTCUT, done"); - } - continue; - } - // If the shortcut is null, we're done. - final String shortcut = cursor.getString(shortcutIndex); - if (shortcut == null) { - if (DebugFlags.DEBUG_ENABLED) { - Log.d(mTag, "loadPersonalDictionary() : Null shortcut"); - } - continue; - } - // Else, save the shortcut. - HashMap<String, String> localeShortcuts = shortcutsPerLocale.get(dictLocale); - if (localeShortcuts == null) { - localeShortcuts = new HashMap<>(); - shortcutsPerLocale.put(dictLocale, localeShortcuts); - } - // Map to the raw input, which might be capitalized. - // This lets the user create a shortcut from "gm" to "General Motors". - localeShortcuts.put(shortcut, rawDictWord); - } - } - - List<DictionaryStats> stats = new ArrayList<>(); - stats.add(new DictionaryStats(ANY_LOCALE, Dictionary.TYPE_USER, dictWords.size())); - int numShortcuts = 0; - for (HashMap<String, String> shortcuts : shortcutsPerLocale.values()) { - numShortcuts += shortcuts.size(); - } - stats.add(new DictionaryStats(ANY_LOCALE, Dictionary.TYPE_USER_SHORTCUT, numShortcuts)); - mDictionaryStats = stats; - - // Atomically replace the copy of mDictWords and mShortcuts. - mDictWords = dictWords; - mShortcutsPerLocale = shortcutsPerLocale; - - // Allow other calls to loadPersonalDictionary to execute now. - mIsLoading.set(false); - - Log.i(mTag, "loadPersonalDictionary() : Loaded " + mDictWords.size() - + " words and " + numShortcuts + " shortcuts"); - - notifyListeners(); - } -} diff --git a/java/src/com/android/inputmethod/latin/about/AboutPreferences.java b/java/src/com/android/inputmethod/latin/about/AboutPreferences.java new file mode 100644 index 000000000..f60b189f1 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/about/AboutPreferences.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 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.inputmethod.latin.about; + +import android.app.Fragment; + +/** + * Dummy class of AboutPreferences. Never use this. + */ +public final class AboutPreferences extends Fragment { + private AboutPreferences() { + // Prevents this from being instantiated + } +} diff --git a/java/src/com/android/inputmethod/latin/accounts/AccountStateChangedListener.java b/java/src/com/android/inputmethod/latin/accounts/AccountStateChangedListener.java new file mode 100644 index 000000000..3c39c9a16 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/accounts/AccountStateChangedListener.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2014 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.inputmethod.latin.accounts; + +import androidx.annotation.NonNull; + +import javax.annotation.Nullable; + +/** + * Handles changes to account used to sign in to the keyboard. + * e.g. account switching/sign-in/sign-out from the keyboard + * user toggling the sync preference. + */ +public class AccountStateChangedListener { + + /** + * Called when the current account being used in keyboard is signed out. + * + * @param oldAccount the account that was signed out of. + */ + public static void onAccountSignedOut(@NonNull String oldAccount) { + } + + /** + * Called when the user signs-in to the keyboard. + * This may be called when the user switches accounts to sign in with a different account. + * + * @param oldAccount the previous account that was being used for sign-in. + * May be null for a fresh sign-in. + * @param newAccount the account being used for sign-in. + */ + public static void onAccountSignedIn(@Nullable String oldAccount, @NonNull String newAccount) { + } + + /** + * Called when the user toggles the sync preference. + * + * @param account the account being used for sync. + * @param syncEnabled indicates whether sync has been enabled or not. + */ + public static void onSyncPreferenceChanged(@Nullable String account, boolean syncEnabled) { + } + + /** + * Forces an immediate sync to happen. + * This should only be used for debugging purposes. + * + * @param account the account to use for sync. + */ + public static void forceSync(@Nullable String account) { + } + + /** + * Forces an immediate deletion of user's data. + * This should only be used for debugging purposes. + * + * @param account the account to use for sync. + */ + public static void forceDelete(@Nullable String account) { + } +} diff --git a/java/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java b/java/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java new file mode 100644 index 000000000..dcc64a223 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2014 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.inputmethod.latin.accounts; + +import android.content.Context; + +import javax.annotation.Nonnull; + +/** + * Utility class for retrieving accounts that may be used for login. + */ +public class LoginAccountUtils { + /** + * This defines the type of account this class deals with. + * This account type is used when listing the accounts available on the device for login. + */ + public static final String ACCOUNT_TYPE = ""; + + private LoginAccountUtils() { + // This utility class is not publicly instantiable. + } + + /** + * Get the accounts available for login. + * + * @return an array of accounts. Empty (never null) if no accounts are available for login. + */ + @Nonnull + @SuppressWarnings("unused") + public static String[] getAccountsForLogin(final Context context) { + return new String[0]; + } +} diff --git a/java/src/com/android/inputmethod/latin/define/DebugFlags.java b/java/src/com/android/inputmethod/latin/define/DebugFlags.java new file mode 100644 index 000000000..c509e8322 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/define/DebugFlags.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2014 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.inputmethod.latin.define; + +import android.content.SharedPreferences; + +public final class DebugFlags { + public static final boolean DEBUG_ENABLED = false; + + private DebugFlags() { + // This class is not publicly instantiable. + } + + @SuppressWarnings("unused") + public static void init(final SharedPreferences prefs) { + } +} diff --git a/java/src/com/android/inputmethod/latin/define/DecoderSpecificConstants.java b/java/src/com/android/inputmethod/latin/define/DecoderSpecificConstants.java new file mode 100644 index 000000000..7f57ce858 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/define/DecoderSpecificConstants.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 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.inputmethod.latin.define; + +/** + * Decoder specific constants for LatinIme. + */ +public class DecoderSpecificConstants { + + // Must be equal to MAX_WORD_LENGTH in native/jni/src/defines.h + public static final int DICTIONARY_MAX_WORD_LENGTH = 48; + + // (MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1)-gram is supported in Java side. Needs to modify + // MAX_PREV_WORD_COUNT_FOR_N_GRAM in native/jni/src/defines.h for suggestions. + public static final int MAX_PREV_WORD_COUNT_FOR_N_GRAM = 3; + + public static final String DECODER_DICT_SUFFIX = ""; + + public static final boolean SHOULD_VERIFY_MAGIC_NUMBER = true; + public static final boolean SHOULD_VERIFY_CHECKSUM = true; + public static final boolean SHOULD_USE_DICT_VERSION = true; + public static final boolean SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION = false; + public static final boolean SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION = true; +} diff --git a/java/src/com/android/inputmethod/latin/define/JniLibName.java b/java/src/com/android/inputmethod/latin/define/JniLibName.java new file mode 100644 index 000000000..abfc36d39 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/define/JniLibName.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 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.inputmethod.latin.define; + +public final class JniLibName { + private JniLibName() { + // This class is not publicly instantiable. + } + + public static final String JNI_LIB_NAME = "jni_latinime"; +} diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlags.java b/java/src/com/android/inputmethod/latin/define/ProductionFlags.java new file mode 100644 index 000000000..f31c20822 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/define/ProductionFlags.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2012 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.inputmethod.latin.define; + +public final class ProductionFlags { + private ProductionFlags() { + // This class is not publicly instantiable. + } + + public static final boolean IS_HARDWARE_KEYBOARD_SUPPORTED = false; + + /** + * Include all suggestions from all dictionaries in + * {@link com.android.inputmethod.latin.SuggestedWords#mRawSuggestions}. + */ + public static final boolean INCLUDE_RAW_SUGGESTIONS = false; + + /** + * When false, the metrics logging is not yet ready to be enabled. + */ + public static final boolean IS_METRICS_LOGGING_SUPPORTED = false; + + /** + * When {@code false}, the split keyboard is not yet ready to be enabled. + */ + public static final boolean IS_SPLIT_KEYBOARD_SUPPORTED = true; + + /** + * When {@code false}, account sign-in in keyboard is not yet ready to be enabled. + */ + public static final boolean ENABLE_ACCOUNT_SIGN_IN = false; + + /** + * When {@code true}, user history dictionary sync feature is ready to be enabled. + */ + public static final boolean ENABLE_USER_HISTORY_DICTIONARY_SYNC = + ENABLE_ACCOUNT_SIGN_IN && false; + + /** + * When {@code true}, the IME maintains per account {@link UserHistoryDictionary}. + */ + public static final boolean ENABLE_PER_ACCOUNT_USER_HISTORY_DICTIONARY = + ENABLE_ACCOUNT_SIGN_IN && false; +} diff --git a/java/src/com/android/inputmethod/latin/permissions/PermissionsActivity.java b/java/src/com/android/inputmethod/latin/permissions/PermissionsActivity.java index bdd63fa00..36d8ed943 100644 --- a/java/src/com/android/inputmethod/latin/permissions/PermissionsActivity.java +++ b/java/src/com/android/inputmethod/latin/permissions/PermissionsActivity.java @@ -21,8 +21,8 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.app.ActivityCompat; +import androidx.annotation.NonNull; +import androidx.core.app.ActivityCompat; /** * An activity to help request permissions. It's used when no other activity is available, e.g. in diff --git a/java/src/com/android/inputmethod/latin/permissions/PermissionsUtil.java b/java/src/com/android/inputmethod/latin/permissions/PermissionsUtil.java index 747f64f24..9a618a755 100644 --- a/java/src/com/android/inputmethod/latin/permissions/PermissionsUtil.java +++ b/java/src/com/android/inputmethod/latin/permissions/PermissionsUtil.java @@ -20,9 +20,9 @@ import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; -import android.support.annotation.NonNull; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; +import androidx.annotation.NonNull; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import java.util.ArrayList; import java.util.List; diff --git a/java/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java b/java/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java new file mode 100644 index 000000000..4e8a10b1f --- /dev/null +++ b/java/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2013 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.inputmethod.latin.settings; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceFragment; +import android.view.inputmethod.InputMethodSubtype; + +import com.android.inputmethod.latin.RichInputMethodSubtype; +import com.android.inputmethod.latin.RichInputMethodManager; + +import javax.annotation.Nonnull; + +/** + * Utility class for managing additional features settings. + */ +@SuppressWarnings("unused") +public class AdditionalFeaturesSettingUtils { + public static final int ADDITIONAL_FEATURES_SETTINGS_SIZE = 0; + + private AdditionalFeaturesSettingUtils() { + // This utility class is not publicly instantiable. + } + + public static void addAdditionalFeaturesPreferences( + final Context context, final PreferenceFragment settingsFragment) { + // do nothing. + } + + public static void readAdditionalFeaturesPreferencesIntoArray(final Context context, + final SharedPreferences prefs, final int[] additionalFeaturesPreferences) { + // do nothing. + } + + @Nonnull + public static RichInputMethodSubtype createRichInputMethodSubtype( + @Nonnull final RichInputMethodManager imm, + @Nonnull final InputMethodSubtype subtype, + final Context context) { + return new RichInputMethodSubtype(subtype); + } +} diff --git a/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java index 46fcc7106..56e8f1623 100644 --- a/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java @@ -26,7 +26,7 @@ import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceGroup; -import android.support.v4.view.ViewCompat; +import androidx.core.view.ViewCompat; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java index a7d157a6b..ac1657762 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java @@ -25,7 +25,7 @@ import android.app.ActionBar; import android.content.Intent; import android.os.Bundle; import android.preference.PreferenceActivity; -import android.support.v4.app.ActivityCompat; +import androidx.core.app.ActivityCompat; import android.view.MenuItem; public final class SettingsActivity extends PreferenceActivity diff --git a/java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java b/java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java index 73d25f6aa..789694f08 100644 --- a/java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java +++ b/java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java @@ -21,7 +21,7 @@ import android.content.res.ColorStateList; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; -import android.support.v4.view.ViewCompat; +import androidx.core.view.ViewCompat; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; diff --git a/java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java b/java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java index 6734e61b8..9a39ceace 100644 --- a/java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java +++ b/java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java @@ -20,7 +20,7 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; -import android.support.v4.view.ViewCompat; +import androidx.core.view.ViewCompat; import android.util.AttributeSet; import android.view.View; diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java index 356d9d021..5f99f9004 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java @@ -24,7 +24,7 @@ import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceActivity; -import android.support.v4.app.ActivityCompat; +import androidx.core.app.ActivityCompat; /** * Spell checker preference screen. diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index c1d1fad68..840a4aa3d 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -21,7 +21,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.drawable.Drawable; -import android.support.v4.view.ViewCompat; +import androidx.core.view.ViewCompat; import android.text.TextUtils; import android.util.AttributeSet; import android.util.TypedValue; diff --git a/java/src/com/android/inputmethod/latin/touchinputconsumer/GestureConsumer.java b/java/src/com/android/inputmethod/latin/touchinputconsumer/GestureConsumer.java new file mode 100644 index 000000000..8291b4f72 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/touchinputconsumer/GestureConsumer.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2014 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.inputmethod.latin.touchinputconsumer; + +import android.view.inputmethod.EditorInfo; + +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.DictionaryFacilitator; +import com.android.inputmethod.latin.SuggestedWords; +import com.android.inputmethod.latin.common.InputPointers; +import com.android.inputmethod.latin.inputlogic.PrivateCommandPerformer; + +import java.util.Locale; + +/** + * Stub for GestureConsumer. + * <br> + * The methods of this class should only be called from a single thread, e.g., + * the UI Thread. + */ +@SuppressWarnings("unused") +public class GestureConsumer { + public static final GestureConsumer NULL_GESTURE_CONSUMER = + new GestureConsumer(); + + public static GestureConsumer newInstance( + final EditorInfo editorInfo, final PrivateCommandPerformer commandPerformer, + final Locale locale, final Keyboard keyboard) { + return GestureConsumer.NULL_GESTURE_CONSUMER; + } + + private GestureConsumer() { + } + + public boolean willConsume() { + return false; + } + + public void onInit(final Locale locale, final Keyboard keyboard) { + } + + public void onGestureStarted(final Locale locale, final Keyboard keyboard) { + } + + public void onGestureCanceled() { + } + + public void onGestureCompleted(final InputPointers inputPointers) { + } + + public void onImeSuggestionsProcessed(final SuggestedWords suggestedWords, + final int composingStart, final int composingLength, + final DictionaryFacilitator dictionaryFacilitator) { + } +} diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryHeaderUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryHeaderUtils.java new file mode 100644 index 000000000..5eb613c9b --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/DictionaryHeaderUtils.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2015 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.inputmethod.latin.utils; + +import com.android.inputmethod.latin.AssetFileAddress; +import com.android.inputmethod.latin.makedict.DictionaryHeader; + +import java.io.File; + +public class DictionaryHeaderUtils { + + public static int getContentVersion(AssetFileAddress fileAddress) { + final DictionaryHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull( + new File(fileAddress.mFilename), fileAddress.mOffset, fileAddress.mLength); + return Integer.parseInt(header.mVersionString); + } +} diff --git a/java/src/com/android/inputmethod/latin/utils/FeedbackUtils.java b/java/src/com/android/inputmethod/latin/utils/FeedbackUtils.java new file mode 100644 index 000000000..67de8ba32 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/FeedbackUtils.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2013 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.inputmethod.latin.utils; + +import android.content.Context; +import android.content.Intent; + +@SuppressWarnings("unused") +public class FeedbackUtils { + public static boolean isHelpAndFeedbackFormSupported() { + return false; + } + + public static void showHelpAndFeedbackForm(Context context) { + } + + public static int getAboutKeyboardTitleResId() { + return 0; + } + + public static Intent getAboutKeyboardIntent(Context context) { + return null; + } +} diff --git a/java/src/com/android/inputmethod/latin/utils/FileTransforms.java b/java/src/com/android/inputmethod/latin/utils/FileTransforms.java new file mode 100644 index 000000000..9f4584ec9 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/FileTransforms.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011 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.inputmethod.latin.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.GZIPInputStream; + +public final class FileTransforms { + public static OutputStream getCryptedStream(OutputStream out) { + // Crypt the stream. + return out; + } + + public static InputStream getDecryptedStream(InputStream in) { + // Decrypt the stream. + return in; + } + + public static InputStream getUncompressedStream(InputStream in) throws IOException { + return new GZIPInputStream(in); + } +} diff --git a/java/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java b/java/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java new file mode 100644 index 000000000..ef1872bf4 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2014 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.inputmethod.latin.utils; + +import android.content.Context; + +import com.android.inputmethod.annotations.UsedForTesting; + +public class ManagedProfileUtils { + private static ManagedProfileUtils INSTANCE = new ManagedProfileUtils(); + private static ManagedProfileUtils sTestInstance; + + private ManagedProfileUtils() { + // This utility class is not publicly instantiable. + } + + @UsedForTesting + public static void setTestInstance(final ManagedProfileUtils testInstance) { + sTestInstance = testInstance; + } + + public static ManagedProfileUtils getInstance() { + return sTestInstance == null ? INSTANCE : sTestInstance; + } + + public boolean hasWorkProfile(final Context context) { + return false; + } +}
\ No newline at end of file diff --git a/java/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java b/java/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java new file mode 100644 index 000000000..97fb17de3 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2013 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.inputmethod.latin.utils; + +import com.android.inputmethod.latin.R; + +import android.content.Context; + +/** + * Helper class to get the metadata URI and the additional ID. + */ +@SuppressWarnings("unused") +public class MetadataFileUriGetter { + private MetadataFileUriGetter() { + // This helper class is not instantiable. + } + + public static String getMetadataUri(final Context context) { + return context.getString(R.string.dictionary_pack_metadata_uri); + } + + public static String getMetadataAdditionalId(final Context context) { + return ""; + } +} diff --git a/java/src/com/android/inputmethod/latin/utils/StatsUtils.java b/java/src/com/android/inputmethod/latin/utils/StatsUtils.java new file mode 100644 index 000000000..03e58478b --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/StatsUtils.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2014 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.inputmethod.latin.utils; + +import android.view.inputmethod.InputMethodSubtype; + +import com.android.inputmethod.latin.DictionaryFacilitator; +import com.android.inputmethod.latin.RichInputMethodManager; +import com.android.inputmethod.latin.SuggestedWords; +import com.android.inputmethod.latin.settings.SettingsValues; + +import javax.annotation.Nullable; + +@SuppressWarnings("unused") +public final class StatsUtils { + + private StatsUtils() { + // Intentional empty constructor. + } + + public static void onCreate(final SettingsValues settingsValues, + RichInputMethodManager richImm) { + } + + public static void onPickSuggestionManually(final SuggestedWords suggestedWords, + final SuggestedWords.SuggestedWordInfo suggestionInfo, + final DictionaryFacilitator dictionaryFacilitator) { + } + + public static void onBackspaceWordDelete(int wordLength) { + } + + public static void onBackspacePressed(int lengthToDelete) { + } + + public static void onBackspaceSelectedText(int selectedTextLength) { + } + + public static void onDeleteMultiCharInput(int multiCharLength) { + } + + public static void onRevertAutoCorrect() { + } + + public static void onRevertDoubleSpacePeriod() { + } + + public static void onRevertSwapPunctuation() { + } + + public static void onFinishInputView() { + } + + public static void onCreateInputView() { + } + + public static void onStartInputView(int inputType, int displayOrientation, boolean restarting) { + } + + public static void onAutoCorrection(final String typedWord, final String autoCorrectionWord, + final boolean isBatchInput, final DictionaryFacilitator dictionaryFacilitator, + final String prevWordsContext) { + } + + public static void onWordCommitUserTyped(final String commitWord, final boolean isBatchMode) { + } + + public static void onWordCommitAutoCorrect(final String commitWord, final boolean isBatchMode) { + } + + public static void onWordCommitSuggestionPickedManually( + final String commitWord, final boolean isBatchMode) { + } + + public static void onDoubleSpacePeriod() { + } + + public static void onLoadSettings(SettingsValues settingsValues) { + } + + public static void onInvalidWordIdentification(final String invalidWord) { + } + + public static void onSubtypeChanged(final InputMethodSubtype oldSubtype, + final InputMethodSubtype newSubtype) { + } + + public static void onSettingsActivity(final String entryPoint) { + } + + public static void onInputConnectionLaggy(final int operation, final long duration) { + } + + public static void onDecoderLaggy(final int operation, final long duration) { + } +} diff --git a/java/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java b/java/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java new file mode 100644 index 000000000..cd42f50c7 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2014 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.inputmethod.latin.utils; + +import android.content.Context; + +import com.android.inputmethod.latin.DictionaryFacilitator; +import com.android.inputmethod.latin.settings.SettingsValues; + +@SuppressWarnings("unused") +public class StatsUtilsManager { + + private static final StatsUtilsManager sInstance = new StatsUtilsManager(); + private static StatsUtilsManager sTestInstance = null; + + /** + * @return the singleton instance of {@link StatsUtilsManager}. + */ + public static StatsUtilsManager getInstance() { + return sTestInstance != null ? sTestInstance : sInstance; + } + + public static void setTestInstance(final StatsUtilsManager testInstance) { + sTestInstance = testInstance; + } + + public void onCreate(final Context context, final DictionaryFacilitator dictionaryFacilitator) { + } + + public void onLoadSettings(final Context context, final SettingsValues settingsValues) { + } + + public void onStartInputView() { + } + + public void onFinishInputView() { + } + + public void onDestroy(final Context context) { + } +} diff --git a/java/src/com/android/inputmethodcommon/InputMethodSettingsActivity.java b/java/src/com/android/inputmethodcommon/InputMethodSettingsActivity.java new file mode 100644 index 000000000..6e868c9ff --- /dev/null +++ b/java/src/com/android/inputmethodcommon/InputMethodSettingsActivity.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2011 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.inputmethodcommon; + +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.preference.PreferenceActivity; + +/** + * This is a helper class for an IME's settings preference activity. It's recommended for every + * IME to have its own settings preference activity which inherits this class. + */ +public abstract class InputMethodSettingsActivity extends PreferenceActivity + implements InputMethodSettingsInterface { + private final InputMethodSettingsImpl mSettings = new InputMethodSettingsImpl(); + @SuppressWarnings("deprecation") + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setPreferenceScreen(getPreferenceManager().createPreferenceScreen(this)); + mSettings.init(this, getPreferenceScreen()); + } + + /** + * {@inheritDoc} + */ + @Override + public void setInputMethodSettingsCategoryTitle(int resId) { + mSettings.setInputMethodSettingsCategoryTitle(resId); + } + + /** + * {@inheritDoc} + */ + @Override + public void setInputMethodSettingsCategoryTitle(CharSequence title) { + mSettings.setInputMethodSettingsCategoryTitle(title); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerTitle(int resId) { + mSettings.setSubtypeEnablerTitle(resId); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerTitle(CharSequence title) { + mSettings.setSubtypeEnablerTitle(title); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerIcon(int resId) { + mSettings.setSubtypeEnablerIcon(resId); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerIcon(Drawable drawable) { + mSettings.setSubtypeEnablerIcon(drawable); + } + + /** + * {@inheritDoc} + */ + @Override + public void onResume() { + super.onResume(); + mSettings.updateSubtypeEnabler(); + } +} diff --git a/java/src/com/android/inputmethodcommon/InputMethodSettingsFragment.java b/java/src/com/android/inputmethodcommon/InputMethodSettingsFragment.java new file mode 100644 index 000000000..49f0b87f1 --- /dev/null +++ b/java/src/com/android/inputmethodcommon/InputMethodSettingsFragment.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2011 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.inputmethodcommon; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.preference.PreferenceFragment; + +/** + * This is a helper class for an IME's settings preference fragment. It's recommended for every + * IME to have its own settings preference fragment which inherits this class. + */ +public abstract class InputMethodSettingsFragment extends PreferenceFragment + implements InputMethodSettingsInterface { + private final InputMethodSettingsImpl mSettings = new InputMethodSettingsImpl(); + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final Context context = getActivity(); + setPreferenceScreen(getPreferenceManager().createPreferenceScreen(context)); + mSettings.init(context, getPreferenceScreen()); + } + + /** + * {@inheritDoc} + */ + @Override + public void setInputMethodSettingsCategoryTitle(int resId) { + mSettings.setInputMethodSettingsCategoryTitle(resId); + } + + /** + * {@inheritDoc} + */ + @Override + public void setInputMethodSettingsCategoryTitle(CharSequence title) { + mSettings.setInputMethodSettingsCategoryTitle(title); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerTitle(int resId) { + mSettings.setSubtypeEnablerTitle(resId); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerTitle(CharSequence title) { + mSettings.setSubtypeEnablerTitle(title); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerIcon(int resId) { + mSettings.setSubtypeEnablerIcon(resId); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerIcon(Drawable drawable) { + mSettings.setSubtypeEnablerIcon(drawable); + } + + /** + * {@inheritDoc} + */ + @Override + public void onResume() { + super.onResume(); + mSettings.updateSubtypeEnabler(); + } +} diff --git a/java/src/com/android/inputmethodcommon/InputMethodSettingsImpl.java b/java/src/com/android/inputmethodcommon/InputMethodSettingsImpl.java new file mode 100644 index 000000000..cfa1a6596 --- /dev/null +++ b/java/src/com/android/inputmethodcommon/InputMethodSettingsImpl.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2011 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.inputmethodcommon; + +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceClickListener; +import android.preference.PreferenceScreen; +import android.provider.Settings; +import android.text.TextUtils; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodManager; +import android.view.inputmethod.InputMethodSubtype; + +import java.util.List; + +/* package private */ class InputMethodSettingsImpl implements InputMethodSettingsInterface { + private Preference mSubtypeEnablerPreference; + private int mInputMethodSettingsCategoryTitleRes; + private CharSequence mInputMethodSettingsCategoryTitle; + private int mSubtypeEnablerTitleRes; + private CharSequence mSubtypeEnablerTitle; + private int mSubtypeEnablerIconRes; + private Drawable mSubtypeEnablerIcon; + private InputMethodManager mImm; + private InputMethodInfo mImi; + + /** + * Initialize internal states of this object. + * @param context the context for this application. + * @param prefScreen a PreferenceScreen of PreferenceActivity or PreferenceFragment. + * @return true if this application is an IME and has two or more subtypes, false otherwise. + */ + public boolean init(final Context context, final PreferenceScreen prefScreen) { + mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + mImi = getMyImi(context, mImm); + if (mImi == null || mImi.getSubtypeCount() <= 1) { + return false; + } + final Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS); + intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, mImi.getId()); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + mSubtypeEnablerPreference = new Preference(context); + mSubtypeEnablerPreference.setIntent(intent); + prefScreen.addPreference(mSubtypeEnablerPreference); + updateSubtypeEnabler(); + return true; + } + + private static InputMethodInfo getMyImi(Context context, InputMethodManager imm) { + final List<InputMethodInfo> imis = imm.getInputMethodList(); + for (int i = 0; i < imis.size(); ++i) { + final InputMethodInfo imi = imis.get(i); + if (imis.get(i).getPackageName().equals(context.getPackageName())) { + return imi; + } + } + return null; + } + + private static String getEnabledSubtypesLabel( + Context context, InputMethodManager imm, InputMethodInfo imi) { + if (context == null || imm == null || imi == null) return null; + final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(imi, true); + final StringBuilder sb = new StringBuilder(); + final int N = subtypes.size(); + for (int i = 0; i < N; ++i) { + final InputMethodSubtype subtype = subtypes.get(i); + if (sb.length() > 0) { + sb.append(", "); + } + sb.append(subtype.getDisplayName(context, imi.getPackageName(), + imi.getServiceInfo().applicationInfo)); + } + return sb.toString(); + } + /** + * {@inheritDoc} + */ + @Override + public void setInputMethodSettingsCategoryTitle(int resId) { + mInputMethodSettingsCategoryTitleRes = resId; + updateSubtypeEnabler(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setInputMethodSettingsCategoryTitle(CharSequence title) { + mInputMethodSettingsCategoryTitleRes = 0; + mInputMethodSettingsCategoryTitle = title; + updateSubtypeEnabler(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerTitle(int resId) { + mSubtypeEnablerTitleRes = resId; + updateSubtypeEnabler(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerTitle(CharSequence title) { + mSubtypeEnablerTitleRes = 0; + mSubtypeEnablerTitle = title; + updateSubtypeEnabler(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerIcon(int resId) { + mSubtypeEnablerIconRes = resId; + updateSubtypeEnabler(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSubtypeEnablerIcon(Drawable drawable) { + mSubtypeEnablerIconRes = 0; + mSubtypeEnablerIcon = drawable; + updateSubtypeEnabler(); + } + + public void updateSubtypeEnabler() { + final Preference pref = mSubtypeEnablerPreference; + if (pref == null) { + return; + } + final Context context = pref.getContext(); + final CharSequence title; + if (mSubtypeEnablerTitleRes != 0) { + title = context.getString(mSubtypeEnablerTitleRes); + } else { + title = mSubtypeEnablerTitle; + } + pref.setTitle(title); + final Intent intent = pref.getIntent(); + if (intent != null) { + intent.putExtra(Intent.EXTRA_TITLE, title); + } + final String summary = getEnabledSubtypesLabel(context, mImm, mImi); + if (!TextUtils.isEmpty(summary)) { + pref.setSummary(summary); + } + if (mSubtypeEnablerIconRes != 0) { + pref.setIcon(mSubtypeEnablerIconRes); + } else { + pref.setIcon(mSubtypeEnablerIcon); + } + } +} diff --git a/java/src/com/android/inputmethodcommon/InputMethodSettingsInterface.java b/java/src/com/android/inputmethodcommon/InputMethodSettingsInterface.java new file mode 100644 index 000000000..6e97faeb7 --- /dev/null +++ b/java/src/com/android/inputmethodcommon/InputMethodSettingsInterface.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011 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.inputmethodcommon; + +import android.graphics.drawable.Drawable; + +/** + * InputMethodSettingsInterface is the interface for adding IME related preferences to + * PreferenceActivity or PreferenceFragment. + */ +public interface InputMethodSettingsInterface { + /** + * Sets the title for the input method settings category with a resource ID. + * @param resId The resource ID of the title. + */ + public void setInputMethodSettingsCategoryTitle(int resId); + + /** + * Sets the title for the input method settings category with a CharSequence. + * @param title The title for this preference. + */ + public void setInputMethodSettingsCategoryTitle(CharSequence title); + + /** + * Sets the title for the input method enabler preference for launching subtype enabler with a + * resource ID. + * @param resId The resource ID of the title. + */ + public void setSubtypeEnablerTitle(int resId); + + /** + * Sets the title for the input method enabler preference for launching subtype enabler with a + * CharSequence. + * @param title The title for this preference. + */ + public void setSubtypeEnablerTitle(CharSequence title); + + /** + * Sets the icon for the preference for launching subtype enabler with a resource ID. + * @param resId The resource id of an optional icon for the preference. + */ + public void setSubtypeEnablerIcon(int resId); + + /** + * Sets the icon for the Preference for launching subtype enabler with a Drawable. + * @param drawable The drawable of an optional icon for the preference. + */ + public void setSubtypeEnablerIcon(Drawable drawable); +} |