am 689cff2e: Merge "[IL21] Move the workaround utils to a better place."
* commit '689cff2e3b1ad3709033b36040dc8607a7cb53d6': [IL21] Move the workaround utils to a better place.main
commit
d9b075eb24
|
@ -23,10 +23,10 @@ import android.os.Build.VERSION_CODES;
|
||||||
* A class to encapsulate work-arounds specific to particular apps.
|
* A class to encapsulate work-arounds specific to particular apps.
|
||||||
*/
|
*/
|
||||||
public class AppWorkaroundsUtils {
|
public class AppWorkaroundsUtils {
|
||||||
private PackageInfo mPackageInfo; // May be null
|
private final PackageInfo mPackageInfo; // May be null
|
||||||
private boolean mIsBrokenByRecorrection = false;
|
private final boolean mIsBrokenByRecorrection;
|
||||||
|
|
||||||
public void setPackageInfo(final PackageInfo packageInfo) {
|
public AppWorkaroundsUtils(final PackageInfo packageInfo) {
|
||||||
mPackageInfo = packageInfo;
|
mPackageInfo = packageInfo;
|
||||||
mIsBrokenByRecorrection = AppWorkaroundsHelper.evaluateIsBrokenByRecorrection(
|
mIsBrokenByRecorrection = AppWorkaroundsHelper.evaluateIsBrokenByRecorrection(
|
||||||
packageInfo);
|
packageInfo);
|
||||||
|
|
|
@ -29,6 +29,7 @@ import com.android.inputmethod.latin.utils.StringUtils;
|
||||||
public final class InputAttributes {
|
public final class InputAttributes {
|
||||||
private final String TAG = InputAttributes.class.getSimpleName();
|
private final String TAG = InputAttributes.class.getSimpleName();
|
||||||
|
|
||||||
|
final public String mTargetApplicationPackageName;
|
||||||
final public boolean mInputTypeNoAutoCorrect;
|
final public boolean mInputTypeNoAutoCorrect;
|
||||||
final public boolean mIsSettingsSuggestionStripOn;
|
final public boolean mIsSettingsSuggestionStripOn;
|
||||||
final public boolean mApplicationSpecifiedCompletionOn;
|
final public boolean mApplicationSpecifiedCompletionOn;
|
||||||
|
@ -36,6 +37,7 @@ public final class InputAttributes {
|
||||||
final private int mInputType;
|
final private int mInputType;
|
||||||
|
|
||||||
public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) {
|
public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) {
|
||||||
|
mTargetApplicationPackageName = null != editorInfo ? editorInfo.packageName : null;
|
||||||
final int inputType = null != editorInfo ? editorInfo.inputType : 0;
|
final int inputType = null != editorInfo ? editorInfo.inputType : 0;
|
||||||
final int inputClass = inputType & InputType.TYPE_MASK_CLASS;
|
final int inputClass = inputType & InputType.TYPE_MASK_CLASS;
|
||||||
mInputType = inputType;
|
mInputType = inputType;
|
||||||
|
|
|
@ -28,7 +28,6 @@ import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
@ -61,7 +60,6 @@ import android.view.inputmethod.InputMethodSubtype;
|
||||||
import com.android.inputmethod.accessibility.AccessibilityUtils;
|
import com.android.inputmethod.accessibility.AccessibilityUtils;
|
||||||
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
|
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.compat.AppWorkaroundsUtils;
|
|
||||||
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
|
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
|
||||||
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
|
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
|
||||||
import com.android.inputmethod.keyboard.Keyboard;
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
|
@ -89,7 +87,6 @@ import com.android.inputmethod.latin.utils.IntentUtils;
|
||||||
import com.android.inputmethod.latin.utils.JniUtils;
|
import com.android.inputmethod.latin.utils.JniUtils;
|
||||||
import com.android.inputmethod.latin.utils.LatinImeLoggerUtils;
|
import com.android.inputmethod.latin.utils.LatinImeLoggerUtils;
|
||||||
import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
|
import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
|
||||||
import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask;
|
|
||||||
import com.android.inputmethod.latin.utils.TextRange;
|
import com.android.inputmethod.latin.utils.TextRange;
|
||||||
import com.android.inputmethod.research.ResearchLogger;
|
import com.android.inputmethod.research.ResearchLogger;
|
||||||
|
|
||||||
|
@ -102,8 +99,7 @@ import java.util.Locale;
|
||||||
* Input method implementation for Qwerty'ish keyboard.
|
* Input method implementation for Qwerty'ish keyboard.
|
||||||
*/
|
*/
|
||||||
public class LatinIME extends InputMethodService implements KeyboardActionListener,
|
public class LatinIME extends InputMethodService implements KeyboardActionListener,
|
||||||
SuggestionStripView.Listener, TargetPackageInfoGetterTask.OnTargetPackageInfoKnownListener,
|
SuggestionStripView.Listener, Suggest.SuggestInitializationListener {
|
||||||
Suggest.SuggestInitializationListener {
|
|
||||||
private static final String TAG = LatinIME.class.getSimpleName();
|
private static final String TAG = LatinIME.class.getSimpleName();
|
||||||
private static final boolean TRACE = false;
|
private static final boolean TRACE = false;
|
||||||
private static boolean DEBUG = false;
|
private static boolean DEBUG = false;
|
||||||
|
@ -128,8 +124,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
private SuggestionStripView mSuggestionStripView;
|
private SuggestionStripView mSuggestionStripView;
|
||||||
|
|
||||||
private CompletionInfo[] mApplicationSpecifiedCompletions;
|
private CompletionInfo[] mApplicationSpecifiedCompletions;
|
||||||
// TODO[IL]: Make this an AsyncResultHolder or a Future in SettingsValues
|
|
||||||
public AppWorkaroundsUtils mAppWorkAroundsUtils = new AppWorkaroundsUtils();
|
|
||||||
|
|
||||||
private RichInputMethodManager mRichImm;
|
private RichInputMethodManager mRichImm;
|
||||||
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
||||||
|
@ -519,9 +513,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
void loadSettings() {
|
void loadSettings() {
|
||||||
final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale();
|
final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale();
|
||||||
final InputAttributes inputAttributes =
|
final EditorInfo editorInfo = getCurrentInputEditorInfo();
|
||||||
new InputAttributes(getCurrentInputEditorInfo(), isFullscreenMode());
|
final InputAttributes inputAttributes = new InputAttributes(editorInfo, isFullscreenMode());
|
||||||
mSettings.loadSettings(locale, inputAttributes);
|
mSettings.loadSettings(this, locale, inputAttributes);
|
||||||
AudioAndHapticFeedbackManager.getInstance().onSettingsChanged(mSettings.getCurrent());
|
AudioAndHapticFeedbackManager.getInstance().onSettingsChanged(mSettings.getCurrent());
|
||||||
// To load the keyboard we need to load all the settings once, but resetting the
|
// To load the keyboard we need to load all the settings once, but resetting the
|
||||||
// contacts dictionary should be deferred until after the new layout has been displayed
|
// contacts dictionary should be deferred until after the new layout has been displayed
|
||||||
|
@ -798,13 +792,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (isDifferentTextField) {
|
if (isDifferentTextField) {
|
||||||
mainKeyboardView.closing();
|
mainKeyboardView.closing();
|
||||||
loadSettings();
|
loadSettings();
|
||||||
final PackageInfo packageInfo =
|
|
||||||
TargetPackageInfoGetterTask.getCachedPackageInfo(editorInfo.packageName);
|
|
||||||
mAppWorkAroundsUtils.setPackageInfo(packageInfo);
|
|
||||||
if (null == packageInfo) {
|
|
||||||
new TargetPackageInfoGetterTask(this /* context */, this /* listener */)
|
|
||||||
.execute(editorInfo.packageName);
|
|
||||||
}
|
|
||||||
currentSettingsValues = mSettings.getCurrent();
|
currentSettingsValues = mSettings.getCurrent();
|
||||||
|
|
||||||
if (suggest != null && currentSettingsValues.mCorrectionEnabled) {
|
if (suggest != null && currentSettingsValues.mCorrectionEnabled) {
|
||||||
|
@ -912,12 +899,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback for the TargetPackageInfoGetterTask
|
|
||||||
@Override
|
|
||||||
public void onTargetPackageInfoKnown(final PackageInfo info) {
|
|
||||||
mAppWorkAroundsUtils.setPackageInfo(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWindowHidden() {
|
public void onWindowHidden() {
|
||||||
super.onWindowHidden();
|
super.onWindowHidden();
|
||||||
|
@ -1991,12 +1972,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
// HACK: We may want to special-case some apps that exhibit bad behavior in case of
|
// HACK: We may want to special-case some apps that exhibit bad behavior in case of
|
||||||
// recorrection. This is a temporary, stopgap measure that will be removed later.
|
// recorrection. This is a temporary, stopgap measure that will be removed later.
|
||||||
// TODO: remove this.
|
// TODO: remove this.
|
||||||
if (mAppWorkAroundsUtils.isBrokenByRecorrection()) return;
|
final SettingsValues settingsValues = mSettings.getCurrent();
|
||||||
|
if (settingsValues.isBrokenByRecorrection()) return;
|
||||||
// A simple way to test for support from the TextView.
|
// A simple way to test for support from the TextView.
|
||||||
if (!isSuggestionsStripVisible()) return;
|
if (!isSuggestionsStripVisible()) return;
|
||||||
// Recorrection is not supported in languages without spaces because we don't know
|
// Recorrection is not supported in languages without spaces because we don't know
|
||||||
// how to segment them yet.
|
// how to segment them yet.
|
||||||
if (!mSettings.getCurrent().mCurrentLanguageHasSpaces) return;
|
if (!settingsValues.mCurrentLanguageHasSpaces) return;
|
||||||
// If the cursor is not touching a word, or if there is a selection, return right away.
|
// If the cursor is not touching a word, or if there is a selection, return right away.
|
||||||
if (mInputLogic.mLastSelectionStart != mInputLogic.mLastSelectionEnd) return;
|
if (mInputLogic.mLastSelectionStart != mInputLogic.mLastSelectionEnd) return;
|
||||||
// If we don't know the cursor location, return.
|
// If we don't know the cursor location, return.
|
||||||
|
@ -2322,8 +2304,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
|
|
||||||
public void debugDumpStateAndCrashWithException(final String context) {
|
public void debugDumpStateAndCrashWithException(final String context) {
|
||||||
final StringBuilder s = new StringBuilder(mAppWorkAroundsUtils.toString());
|
final SettingsValues settingsValues = mSettings.getCurrent();
|
||||||
s.append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes)
|
final StringBuilder s = new StringBuilder(settingsValues.toString());
|
||||||
|
s.append("\nAttributes : ").append(settingsValues.mInputAttributes)
|
||||||
.append("\nContext : ").append(context);
|
.append("\nContext : ").append(context);
|
||||||
throw new RuntimeException(s.toString());
|
throw new RuntimeException(s.toString());
|
||||||
}
|
}
|
||||||
|
@ -2348,5 +2331,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
p.println(" mVibrateOn=" + settingsValues.mVibrateOn);
|
p.println(" mVibrateOn=" + settingsValues.mVibrateOn);
|
||||||
p.println(" mKeyPreviewPopupOn=" + settingsValues.mKeyPreviewPopupOn);
|
p.println(" mKeyPreviewPopupOn=" + settingsValues.mKeyPreviewPopupOn);
|
||||||
p.println(" inputAttributes=" + settingsValues.mInputAttributes);
|
p.println(" inputAttributes=" + settingsValues.mInputAttributes);
|
||||||
|
// TODO: Dump all settings values
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -387,7 +387,7 @@ public final class InputLogic {
|
||||||
final boolean swapWeakSpace = maybeStripSpace(settingsValues,
|
final boolean swapWeakSpace = maybeStripSpace(settingsValues,
|
||||||
codePoint, spaceState, Constants.SUGGESTION_STRIP_COORDINATE == x);
|
codePoint, spaceState, Constants.SUGGESTION_STRIP_COORDINATE == x);
|
||||||
|
|
||||||
sendKeyCodePoint(codePoint);
|
sendKeyCodePoint(settingsValues, codePoint);
|
||||||
|
|
||||||
if (swapWeakSpace) {
|
if (swapWeakSpace) {
|
||||||
swapSwapperAndSpace(keyboardSwitcher);
|
swapSwapperAndSpace(keyboardSwitcher);
|
||||||
|
@ -449,7 +449,7 @@ public final class InputLogic {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldAvoidSendingCode) {
|
if (!shouldAvoidSendingCode) {
|
||||||
sendKeyCodePoint(codePoint);
|
sendKeyCodePoint(settingsValues, codePoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Constants.CODE_SPACE == codePoint) {
|
if (Constants.CODE_SPACE == codePoint) {
|
||||||
|
@ -593,7 +593,7 @@ public final class InputLogic {
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
Log.e(TAG, "Backspace when we don't know the selection position");
|
Log.e(TAG, "Backspace when we don't know the selection position");
|
||||||
}
|
}
|
||||||
if (mLatinIME.mAppWorkAroundsUtils.isBeforeJellyBean() ||
|
if (settingsValues.isBeforeJellyBean() ||
|
||||||
settingsValues.mInputAttributes.isTypeNull()) {
|
settingsValues.mInputAttributes.isTypeNull()) {
|
||||||
// There are two possible reasons to send a key event: either the field has
|
// There are two possible reasons to send a key event: either the field has
|
||||||
// type TYPE_NULL, in which case the keyboard should send events, or we are
|
// type TYPE_NULL, in which case the keyboard should send events, or we are
|
||||||
|
@ -1167,9 +1167,10 @@ public final class InputLogic {
|
||||||
* Normally we send code points with commitText, but there are some cases (where backward
|
* Normally we send code points with commitText, but there are some cases (where backward
|
||||||
* compatibility is a concern for example) where we want to use deprecated methods.
|
* compatibility is a concern for example) where we want to use deprecated methods.
|
||||||
*
|
*
|
||||||
|
* @param settingsValues the current values of the settings.
|
||||||
* @param codePoint the code point to send.
|
* @param codePoint the code point to send.
|
||||||
*/
|
*/
|
||||||
private void sendKeyCodePoint(final int codePoint) {
|
private void sendKeyCodePoint(final SettingsValues settingsValues, final int codePoint) {
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
ResearchLogger.latinIME_sendKeyCodePoint(codePoint);
|
ResearchLogger.latinIME_sendKeyCodePoint(codePoint);
|
||||||
}
|
}
|
||||||
|
@ -1181,8 +1182,7 @@ public final class InputLogic {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we should do this also when the editor has TYPE_NULL
|
// TODO: we should do this also when the editor has TYPE_NULL
|
||||||
if (Constants.CODE_ENTER == codePoint
|
if (Constants.CODE_ENTER == codePoint && settingsValues.isBeforeJellyBean()) {
|
||||||
&& mLatinIME.mAppWorkAroundsUtils.isBeforeJellyBean()) {
|
|
||||||
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
|
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
|
||||||
// a hardware keyboard event on pressing enter or delete. This is bad for many
|
// a hardware keyboard event on pressing enter or delete. This is bad for many
|
||||||
// reasons (there are race conditions with commits) but some applications are
|
// reasons (there are race conditions with commits) but some applications are
|
||||||
|
@ -1209,7 +1209,7 @@ public final class InputLogic {
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
ResearchLogger.latinIME_promotePhantomSpace();
|
ResearchLogger.latinIME_promotePhantomSpace();
|
||||||
}
|
}
|
||||||
sendKeyCodePoint(Constants.CODE_SPACE);
|
sendKeyCodePoint(settingsValues, Constants.CODE_SPACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
public static final String PREF_EMOJI_CATEGORY_LAST_TYPED_ID = "emoji_category_last_typed_id";
|
public static final String PREF_EMOJI_CATEGORY_LAST_TYPED_ID = "emoji_category_last_typed_id";
|
||||||
public static final String PREF_LAST_SHOWN_EMOJI_CATEGORY_ID = "last_shown_emoji_category_id";
|
public static final String PREF_LAST_SHOWN_EMOJI_CATEGORY_ID = "last_shown_emoji_category_id";
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
private Resources mRes;
|
private Resources mRes;
|
||||||
private SharedPreferences mPrefs;
|
private SharedPreferences mPrefs;
|
||||||
private SettingsValues mSettingsValues;
|
private SettingsValues mSettingsValues;
|
||||||
|
@ -121,6 +122,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onCreate(final Context context) {
|
private void onCreate(final Context context) {
|
||||||
|
mContext = context;
|
||||||
mRes = context.getResources();
|
mRes = context.getResources();
|
||||||
mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
mPrefs.registerOnSharedPreferenceChangeListener(this);
|
mPrefs.registerOnSharedPreferenceChangeListener(this);
|
||||||
|
@ -140,20 +142,22 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
Log.w(TAG, "onSharedPreferenceChanged called before loadSettings.");
|
Log.w(TAG, "onSharedPreferenceChanged called before loadSettings.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loadSettings(mSettingsValues.mLocale, mSettingsValues.mInputAttributes);
|
loadSettings(mContext, mSettingsValues.mLocale, mSettingsValues.mInputAttributes);
|
||||||
} finally {
|
} finally {
|
||||||
mSettingsValuesLock.unlock();
|
mSettingsValuesLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadSettings(final Locale locale, final InputAttributes inputAttributes) {
|
public void loadSettings(final Context context, final Locale locale,
|
||||||
|
final InputAttributes inputAttributes) {
|
||||||
mSettingsValuesLock.lock();
|
mSettingsValuesLock.lock();
|
||||||
|
mContext = context;
|
||||||
try {
|
try {
|
||||||
final SharedPreferences prefs = mPrefs;
|
final SharedPreferences prefs = mPrefs;
|
||||||
final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() {
|
final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() {
|
||||||
@Override
|
@Override
|
||||||
protected SettingsValues job(final Resources res) {
|
protected SettingsValues job(final Resources res) {
|
||||||
return new SettingsValues(prefs, locale, res, inputAttributes);
|
return new SettingsValues(context, prefs, locale, res, inputAttributes);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mSettingsValues = job.runInLocale(mRes, locale);
|
mSettingsValues = job.runInLocale(mRes, locale);
|
||||||
|
|
|
@ -16,13 +16,16 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin.settings;
|
package com.android.inputmethod.latin.settings;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
|
import com.android.inputmethod.compat.AppWorkaroundsUtils;
|
||||||
import com.android.inputmethod.keyboard.internal.KeySpecParser;
|
import com.android.inputmethod.keyboard.internal.KeySpecParser;
|
||||||
import com.android.inputmethod.latin.Constants;
|
import com.android.inputmethod.latin.Constants;
|
||||||
import com.android.inputmethod.latin.Dictionary;
|
import com.android.inputmethod.latin.Dictionary;
|
||||||
|
@ -31,8 +34,10 @@ import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.RichInputMethodManager;
|
import com.android.inputmethod.latin.RichInputMethodManager;
|
||||||
import com.android.inputmethod.latin.SuggestedWords;
|
import com.android.inputmethod.latin.SuggestedWords;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
|
import com.android.inputmethod.latin.utils.AsyncResultHolder;
|
||||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||||
import com.android.inputmethod.latin.utils.StringUtils;
|
import com.android.inputmethod.latin.utils.StringUtils;
|
||||||
|
import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -48,6 +53,7 @@ public final class SettingsValues {
|
||||||
// Float.NEGATIVE_INFINITE and Float.MAX_VALUE. Currently used for auto-correction settings.
|
// Float.NEGATIVE_INFINITE and Float.MAX_VALUE. Currently used for auto-correction settings.
|
||||||
private static final String FLOAT_MAX_VALUE_MARKER_STRING = "floatMaxValue";
|
private static final String FLOAT_MAX_VALUE_MARKER_STRING = "floatMaxValue";
|
||||||
private static final String FLOAT_NEGATIVE_INFINITY_MARKER_STRING = "floatNegativeInfinity";
|
private static final String FLOAT_NEGATIVE_INFINITY_MARKER_STRING = "floatNegativeInfinity";
|
||||||
|
private static final int TIMEOUT_TO_GET_TARGET_PACKAGE = 5; // seconds
|
||||||
|
|
||||||
// From resources:
|
// From resources:
|
||||||
public final int mDelayUpdateOldSuggestions;
|
public final int mDelayUpdateOldSuggestions;
|
||||||
|
@ -95,6 +101,7 @@ public final class SettingsValues {
|
||||||
public final int mSuggestionVisibility;
|
public final int mSuggestionVisibility;
|
||||||
public final boolean mBoostPersonalizationDictionaryForDebug;
|
public final boolean mBoostPersonalizationDictionaryForDebug;
|
||||||
public final boolean mUseOnlyPersonalizationDictionaryForDebug;
|
public final boolean mUseOnlyPersonalizationDictionaryForDebug;
|
||||||
|
private final AsyncResultHolder<AppWorkaroundsUtils> mAppWorkarounds;
|
||||||
|
|
||||||
// Setting values for additional features
|
// Setting values for additional features
|
||||||
public final int[] mAdditionalFeaturesSettingValues =
|
public final int[] mAdditionalFeaturesSettingValues =
|
||||||
|
@ -103,8 +110,8 @@ public final class SettingsValues {
|
||||||
// Debug settings
|
// Debug settings
|
||||||
public final boolean mIsInternal;
|
public final boolean mIsInternal;
|
||||||
|
|
||||||
public SettingsValues(final SharedPreferences prefs, final Locale locale, final Resources res,
|
public SettingsValues(final Context context, final SharedPreferences prefs, final Locale locale,
|
||||||
final InputAttributes inputAttributes) {
|
final Resources res, final InputAttributes inputAttributes) {
|
||||||
mLocale = locale;
|
mLocale = locale;
|
||||||
// Get the resources
|
// Get the resources
|
||||||
mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions);
|
mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions);
|
||||||
|
@ -177,6 +184,15 @@ public final class SettingsValues {
|
||||||
Settings.readBoostPersonalizationDictionaryForDebug(prefs);
|
Settings.readBoostPersonalizationDictionaryForDebug(prefs);
|
||||||
mUseOnlyPersonalizationDictionaryForDebug =
|
mUseOnlyPersonalizationDictionaryForDebug =
|
||||||
Settings.readUseOnlyPersonalizationDictionaryForDebug(prefs);
|
Settings.readUseOnlyPersonalizationDictionaryForDebug(prefs);
|
||||||
|
mAppWorkarounds = new AsyncResultHolder<AppWorkaroundsUtils>();
|
||||||
|
final PackageInfo packageInfo = TargetPackageInfoGetterTask.getCachedPackageInfo(
|
||||||
|
mInputAttributes.mTargetApplicationPackageName);
|
||||||
|
if (null != packageInfo) {
|
||||||
|
mAppWorkarounds.set(new AppWorkaroundsUtils(packageInfo));
|
||||||
|
} else {
|
||||||
|
new TargetPackageInfoGetterTask(context, mAppWorkarounds)
|
||||||
|
.execute(mInputAttributes.mTargetApplicationPackageName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only for tests
|
// Only for tests
|
||||||
|
@ -225,6 +241,8 @@ public final class SettingsValues {
|
||||||
mIsInternal = false;
|
mIsInternal = false;
|
||||||
mBoostPersonalizationDictionaryForDebug = false;
|
mBoostPersonalizationDictionaryForDebug = false;
|
||||||
mUseOnlyPersonalizationDictionaryForDebug = false;
|
mUseOnlyPersonalizationDictionaryForDebug = false;
|
||||||
|
mAppWorkarounds = new AsyncResultHolder<AppWorkaroundsUtils>();
|
||||||
|
mAppWorkarounds.set(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
|
@ -288,6 +306,14 @@ public final class SettingsValues {
|
||||||
return mInputAttributes.isSameInputType(editorInfo);
|
return mInputAttributes.isSameInputType(editorInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isBeforeJellyBean() {
|
||||||
|
return mAppWorkarounds.get(null, TIMEOUT_TO_GET_TARGET_PACKAGE).isBeforeJellyBean();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBrokenByRecorrection() {
|
||||||
|
return mAppWorkarounds.get(null, TIMEOUT_TO_GET_TARGET_PACKAGE).isBrokenByRecorrection();
|
||||||
|
}
|
||||||
|
|
||||||
// Helper functions to create member values.
|
// Helper functions to create member values.
|
||||||
private static SuggestedWords createSuggestPuncList(final String[] puncs) {
|
private static SuggestedWords createSuggestPuncList(final String[] puncs) {
|
||||||
final ArrayList<SuggestedWordInfo> puncList = CollectionUtils.newArrayList();
|
final ArrayList<SuggestedWordInfo> puncList = CollectionUtils.newArrayList();
|
||||||
|
|
|
@ -22,6 +22,8 @@ import android.content.pm.PackageManager;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.util.LruCache;
|
import android.util.LruCache;
|
||||||
|
|
||||||
|
import com.android.inputmethod.compat.AppWorkaroundsUtils;
|
||||||
|
|
||||||
public final class TargetPackageInfoGetterTask extends
|
public final class TargetPackageInfoGetterTask extends
|
||||||
AsyncTask<String, Void, PackageInfo> {
|
AsyncTask<String, Void, PackageInfo> {
|
||||||
private static final int MAX_CACHE_ENTRIES = 64; // arbitrary
|
private static final int MAX_CACHE_ENTRIES = 64; // arbitrary
|
||||||
|
@ -37,17 +39,13 @@ public final class TargetPackageInfoGetterTask extends
|
||||||
sCache.remove(packageName);
|
sCache.remove(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnTargetPackageInfoKnownListener {
|
|
||||||
public void onTargetPackageInfoKnown(final PackageInfo info);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private final OnTargetPackageInfoKnownListener mListener;
|
private final AsyncResultHolder<AppWorkaroundsUtils> mResult;
|
||||||
|
|
||||||
public TargetPackageInfoGetterTask(final Context context,
|
public TargetPackageInfoGetterTask(final Context context,
|
||||||
final OnTargetPackageInfoKnownListener listener) {
|
final AsyncResultHolder<AppWorkaroundsUtils> result) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mListener = listener;
|
mResult = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -65,6 +63,6 @@ public final class TargetPackageInfoGetterTask extends
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(final PackageInfo info) {
|
protected void onPostExecute(final PackageInfo info) {
|
||||||
mListener.onTargetPackageInfoKnown(info);
|
mResult.set(new AppWorkaroundsUtils(info));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.settings.Settings;
|
||||||
|
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build.VERSION_CODES;
|
||||||
|
import android.test.suitebuilder.annotation.LargeTest;
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
|
||||||
|
@LargeTest
|
||||||
|
public class AppWorkaroundsTests extends InputTestsBase {
|
||||||
|
String packageNameOfAppBeforeJellyBean;
|
||||||
|
String packageNameOfAppAfterJellyBean;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
// NOTE: this will fail if there is no app installed that targets an SDK
|
||||||
|
// before Jelly Bean. For the moment, it's fine.
|
||||||
|
final PackageManager pm = getContext().getPackageManager();
|
||||||
|
for (ApplicationInfo ai : pm.getInstalledApplications(0 /* flags */)) {
|
||||||
|
if (ai.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
|
||||||
|
packageNameOfAppBeforeJellyBean = ai.packageName;
|
||||||
|
} else {
|
||||||
|
packageNameOfAppAfterJellyBean = ai.packageName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want to test if the app package info is correctly retrieved by LatinIME. Since it
|
||||||
|
// asks this information to the package manager from the package name, and that it takes
|
||||||
|
// the package name from the EditorInfo, all we have to do it put the correct package
|
||||||
|
// name in the editor info.
|
||||||
|
// To this end, our base class InputTestsBase offers a hook for us to touch the EditorInfo.
|
||||||
|
// We override this hook to write the package name that we need.
|
||||||
|
@Override
|
||||||
|
protected EditorInfo enrichEditorInfo(final EditorInfo ei) {
|
||||||
|
if ("testBeforeJellyBeanTrue".equals(getName())) {
|
||||||
|
ei.packageName = packageNameOfAppBeforeJellyBean;
|
||||||
|
} else if ("testBeforeJellyBeanFalse".equals(getName())) {
|
||||||
|
ei.packageName = packageNameOfAppAfterJellyBean;
|
||||||
|
}
|
||||||
|
return ei;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBeforeJellyBeanTrue() {
|
||||||
|
assertTrue("Couldn't successfully detect this app targets < Jelly Bean (package is "
|
||||||
|
+ packageNameOfAppBeforeJellyBean + ")",
|
||||||
|
Settings.getInstance().getCurrent().isBeforeJellyBean());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBeforeJellyBeanFalse() {
|
||||||
|
assertFalse("Couldn't successfully detect this app targets >= Jelly Bean (package is "
|
||||||
|
+ packageNameOfAppAfterJellyBean + ")",
|
||||||
|
Settings.getInstance().getCurrent().isBeforeJellyBean());
|
||||||
|
}
|
||||||
|
}
|
|
@ -162,6 +162,13 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
|
||||||
return setBooleanPreference(PREF_DEBUG_MODE, value, false);
|
return setBooleanPreference(PREF_DEBUG_MODE, value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected EditorInfo enrichEditorInfo(final EditorInfo ei) {
|
||||||
|
// Some tests that inherit from us need to add some data in the EditorInfo (see
|
||||||
|
// AppWorkaroundsTests#enrichEditorInfo() for a concrete example of this). Since we
|
||||||
|
// control the EditorInfo, we supply a hook here for children to override.
|
||||||
|
return ei;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
@ -176,12 +183,13 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
|
||||||
mPreviousAutoCorrectSetting = setStringPreference(PREF_AUTO_CORRECTION_THRESHOLD,
|
mPreviousAutoCorrectSetting = setStringPreference(PREF_AUTO_CORRECTION_THRESHOLD,
|
||||||
DEFAULT_AUTO_CORRECTION_THRESHOLD, DEFAULT_AUTO_CORRECTION_THRESHOLD);
|
DEFAULT_AUTO_CORRECTION_THRESHOLD, DEFAULT_AUTO_CORRECTION_THRESHOLD);
|
||||||
mLatinIME.onCreate();
|
mLatinIME.onCreate();
|
||||||
final EditorInfo ei = new EditorInfo();
|
EditorInfo ei = new EditorInfo();
|
||||||
final InputConnection ic = mEditText.onCreateInputConnection(ei);
|
final InputConnection ic = mEditText.onCreateInputConnection(ei);
|
||||||
final LayoutInflater inflater =
|
final LayoutInflater inflater =
|
||||||
(LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
(LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
final ViewGroup vg = new FrameLayout(getContext());
|
final ViewGroup vg = new FrameLayout(getContext());
|
||||||
mInputView = inflater.inflate(R.layout.input_view, vg);
|
mInputView = inflater.inflate(R.layout.input_view, vg);
|
||||||
|
ei = enrichEditorInfo(ei);
|
||||||
mLatinIME.onCreateInputMethodInterface().startInput(ic, ei);
|
mLatinIME.onCreateInputMethodInterface().startInput(ic, ei);
|
||||||
mLatinIME.setInputView(mInputView);
|
mLatinIME.setInputView(mInputView);
|
||||||
mLatinIME.onBindInput();
|
mLatinIME.onBindInput();
|
||||||
|
|
Loading…
Reference in New Issue