am 7058b02a: Extract a new class for app-specific workarounds.
* commit '7058b02a9c798c21b169b778be2befc7739f4e9b': Extract a new class for app-specific workarounds.main
commit
5906b05bb5
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
|
||||
/**
|
||||
* A class to encapsulate work-arounds specific to particular apps.
|
||||
*/
|
||||
public class AppWorkaroundsUtils {
|
||||
private PackageInfo mPackageInfo; // May be null
|
||||
|
||||
public void setPackageInfo(final PackageInfo packageInfo) {
|
||||
mPackageInfo = packageInfo;
|
||||
}
|
||||
|
||||
public boolean isBeforeJellyBean() {
|
||||
if (null == mPackageInfo || null == mPackageInfo.applicationInfo) {
|
||||
return false;
|
||||
}
|
||||
return mPackageInfo.applicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (null == mPackageInfo || null == mPackageInfo.applicationInfo) {
|
||||
return "";
|
||||
}
|
||||
final StringBuilder s = new StringBuilder();
|
||||
s.append("Target application : ")
|
||||
.append(mPackageInfo.applicationInfo.name)
|
||||
.append("\nPackage : ")
|
||||
.append(mPackageInfo.applicationInfo.packageName)
|
||||
.append("\nTarget app sdk version : ")
|
||||
.append(mPackageInfo.applicationInfo.targetSdkVersion);
|
||||
return s.toString();
|
||||
}
|
||||
}
|
|
@ -75,7 +75,7 @@ public final class DictionaryPackInstallBroadcastReceiver extends BroadcastRecei
|
|||
final String packageName = packageUri.getSchemeSpecificPart();
|
||||
if (null == packageName) return;
|
||||
// TODO: do this in a more appropriate place
|
||||
TargetApplicationGetter.removeApplicationInfoCache(packageName);
|
||||
TargetPackageInfoGetterTask.removeCachedPackageInfo(packageName);
|
||||
final PackageInfo packageInfo;
|
||||
try {
|
||||
packageInfo = manager.getPackageInfo(packageName, PackageManager.GET_PROVIDERS);
|
||||
|
|
|
@ -28,14 +28,13 @@ import android.content.DialogInterface;
|
|||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.media.AudioManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
|
@ -64,6 +63,7 @@ import android.view.inputmethod.InputMethodSubtype;
|
|||
import com.android.inputmethod.accessibility.AccessibilityUtils;
|
||||
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
|
||||
import com.android.inputmethod.annotations.UsedForTesting;
|
||||
import com.android.inputmethod.compat.AppWorkaroundsUtils;
|
||||
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
|
||||
import com.android.inputmethod.compat.SuggestionSpanUtils;
|
||||
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
|
||||
|
@ -91,7 +91,7 @@ import java.util.TreeSet;
|
|||
* Input method implementation for Qwerty'ish keyboard.
|
||||
*/
|
||||
public class LatinIME extends InputMethodService implements KeyboardActionListener,
|
||||
SuggestionStripView.Listener, TargetApplicationGetter.OnTargetApplicationKnownListener,
|
||||
SuggestionStripView.Listener, TargetPackageInfoGetterTask.OnTargetPackageInfoKnownListener,
|
||||
Suggest.SuggestInitializationListener {
|
||||
private static final String TAG = LatinIME.class.getSimpleName();
|
||||
private static final boolean TRACE = false;
|
||||
|
@ -141,7 +141,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
|
||||
@UsedForTesting Suggest mSuggest;
|
||||
private CompletionInfo[] mApplicationSpecifiedCompletions;
|
||||
private ApplicationInfo mTargetApplicationInfo;
|
||||
private AppWorkaroundsUtils mAppWorkAroundsUtils = new AppWorkaroundsUtils();
|
||||
|
||||
private RichInputMethodManager mRichImm;
|
||||
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
||||
|
@ -711,10 +711,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead");
|
||||
}
|
||||
|
||||
mTargetApplicationInfo =
|
||||
TargetApplicationGetter.getCachedApplicationInfo(editorInfo.packageName);
|
||||
if (null == mTargetApplicationInfo) {
|
||||
new TargetApplicationGetter(this /* context */, this /* listener */)
|
||||
final PackageInfo packageInfo =
|
||||
TargetPackageInfoGetterTask.getCachedPackageInfo(editorInfo.packageName);
|
||||
mAppWorkAroundsUtils.setPackageInfo(packageInfo);
|
||||
if (null == packageInfo) {
|
||||
new TargetPackageInfoGetterTask(this /* context */, this /* listener */)
|
||||
.execute(editorInfo.packageName);
|
||||
}
|
||||
|
||||
|
@ -819,10 +820,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
|
||||
}
|
||||
|
||||
// Callback for the TargetApplicationGetter
|
||||
// Callback for the TargetPackageInfoGetterTask
|
||||
@Override
|
||||
public void onTargetApplicationKnown(final ApplicationInfo info) {
|
||||
mTargetApplicationInfo = info;
|
||||
public void onTargetPackageInfoKnown(final PackageInfo info) {
|
||||
mAppWorkAroundsUtils.setPackageInfo(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1369,8 +1370,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
return;
|
||||
}
|
||||
|
||||
if (Constants.CODE_ENTER == code && mTargetApplicationInfo != null
|
||||
&& mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
|
||||
if (Constants.CODE_ENTER == code && mAppWorkAroundsUtils.isBeforeJellyBean()) {
|
||||
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
|
||||
// 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
|
||||
|
@ -1864,8 +1864,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// This should never happen.
|
||||
Log.e(TAG, "Backspace when we don't know the selection position");
|
||||
}
|
||||
if (mTargetApplicationInfo != null
|
||||
&& mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
|
||||
if (mAppWorkAroundsUtils.isBeforeJellyBean()) {
|
||||
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
|
||||
// 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
|
||||
|
@ -2785,12 +2784,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
|
||||
public void debugDumpStateAndCrashWithException(final String context) {
|
||||
final StringBuilder s = new StringBuilder();
|
||||
s.append("Target application : ").append(mTargetApplicationInfo.name)
|
||||
.append("\nPackage : ").append(mTargetApplicationInfo.packageName)
|
||||
.append("\nTarget app sdk version : ")
|
||||
.append(mTargetApplicationInfo.targetSdkVersion)
|
||||
.append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes)
|
||||
final StringBuilder s = new StringBuilder(mAppWorkAroundsUtils.toString());
|
||||
s.append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes)
|
||||
.append("\nContext : ").append(context);
|
||||
throw new RuntimeException(s.toString());
|
||||
}
|
||||
|
|
|
@ -17,54 +17,54 @@
|
|||
package com.android.inputmethod.latin;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.LruCache;
|
||||
|
||||
public final class TargetApplicationGetter extends AsyncTask<String, Void, ApplicationInfo> {
|
||||
public final class TargetPackageInfoGetterTask extends
|
||||
AsyncTask<String, Void, PackageInfo> {
|
||||
private static final int MAX_CACHE_ENTRIES = 64; // arbitrary
|
||||
private static LruCache<String, ApplicationInfo> sCache =
|
||||
new LruCache<String, ApplicationInfo>(MAX_CACHE_ENTRIES);
|
||||
private static final LruCache<String, PackageInfo> sCache =
|
||||
new LruCache<String, PackageInfo>(MAX_CACHE_ENTRIES);
|
||||
|
||||
public static ApplicationInfo getCachedApplicationInfo(final String packageName) {
|
||||
public static PackageInfo getCachedPackageInfo(final String packageName) {
|
||||
if (null == packageName) return null;
|
||||
return sCache.get(packageName);
|
||||
}
|
||||
|
||||
public static void removeApplicationInfoCache(final String packageName) {
|
||||
public static void removeCachedPackageInfo(final String packageName) {
|
||||
sCache.remove(packageName);
|
||||
}
|
||||
|
||||
public interface OnTargetApplicationKnownListener {
|
||||
public void onTargetApplicationKnown(final ApplicationInfo info);
|
||||
public interface OnTargetPackageInfoKnownListener {
|
||||
public void onTargetPackageInfoKnown(final PackageInfo info);
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private final OnTargetApplicationKnownListener mListener;
|
||||
private final OnTargetPackageInfoKnownListener mListener;
|
||||
|
||||
public TargetApplicationGetter(final Context context,
|
||||
final OnTargetApplicationKnownListener listener) {
|
||||
public TargetPackageInfoGetterTask(final Context context,
|
||||
final OnTargetPackageInfoKnownListener listener) {
|
||||
mContext = context;
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ApplicationInfo doInBackground(final String... packageName) {
|
||||
protected PackageInfo doInBackground(final String... packageName) {
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
mContext = null; // Bazooka-powered anti-leak device
|
||||
try {
|
||||
final ApplicationInfo targetAppInfo =
|
||||
pm.getApplicationInfo(packageName[0], 0 /* flags */);
|
||||
sCache.put(packageName[0], targetAppInfo);
|
||||
return targetAppInfo;
|
||||
final PackageInfo packageInfo = pm.getPackageInfo(packageName[0], 0 /* flags */);
|
||||
sCache.put(packageName[0], packageInfo);
|
||||
return packageInfo;
|
||||
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final ApplicationInfo info) {
|
||||
mListener.onTargetApplicationKnown(info);
|
||||
protected void onPostExecute(final PackageInfo info) {
|
||||
mListener.onTargetPackageInfoKnown(info);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue