[IL21] Move the workaround utils to a better place.

Bug: 8636060
Change-Id: I566f9e109ebcabe3a6a778118434ce79d02d1113
main
Jean Chalard 2013-12-20 15:00:44 +09:00
parent 8a390023e1
commit 1404c1af85
9 changed files with 147 additions and 51 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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
} }
} }

View File

@ -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);
} }
} }

View File

@ -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);

View File

@ -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();

View File

@ -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));
} }
} }

View File

@ -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());
}
}

View File

@ -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();