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();
|
final String packageName = packageUri.getSchemeSpecificPart();
|
||||||
if (null == packageName) return;
|
if (null == packageName) return;
|
||||||
// TODO: do this in a more appropriate place
|
// TODO: do this in a more appropriate place
|
||||||
TargetApplicationGetter.removeApplicationInfoCache(packageName);
|
TargetPackageInfoGetterTask.removeCachedPackageInfo(packageName);
|
||||||
final PackageInfo packageInfo;
|
final PackageInfo packageInfo;
|
||||||
try {
|
try {
|
||||||
packageInfo = manager.getPackageInfo(packageName, PackageManager.GET_PROVIDERS);
|
packageInfo = manager.getPackageInfo(packageName, PackageManager.GET_PROVIDERS);
|
||||||
|
|
|
@ -28,14 +28,13 @@ 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.ApplicationInfo;
|
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;
|
||||||
import android.inputmethodservice.InputMethodService;
|
import android.inputmethodservice.InputMethodService;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.os.Build.VERSION_CODES;
|
|
||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
|
@ -64,6 +63,7 @@ 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.compat.SuggestionSpanUtils;
|
import com.android.inputmethod.compat.SuggestionSpanUtils;
|
||||||
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
|
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
|
||||||
|
@ -91,7 +91,7 @@ import java.util.TreeSet;
|
||||||
* 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, TargetApplicationGetter.OnTargetApplicationKnownListener,
|
SuggestionStripView.Listener, TargetPackageInfoGetterTask.OnTargetPackageInfoKnownListener,
|
||||||
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;
|
||||||
|
@ -141,7 +141,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
|
private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
|
||||||
@UsedForTesting Suggest mSuggest;
|
@UsedForTesting Suggest mSuggest;
|
||||||
private CompletionInfo[] mApplicationSpecifiedCompletions;
|
private CompletionInfo[] mApplicationSpecifiedCompletions;
|
||||||
private ApplicationInfo mTargetApplicationInfo;
|
private AppWorkaroundsUtils mAppWorkAroundsUtils = new AppWorkaroundsUtils();
|
||||||
|
|
||||||
private RichInputMethodManager mRichImm;
|
private RichInputMethodManager mRichImm;
|
||||||
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
|
@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");
|
Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
mTargetApplicationInfo =
|
final PackageInfo packageInfo =
|
||||||
TargetApplicationGetter.getCachedApplicationInfo(editorInfo.packageName);
|
TargetPackageInfoGetterTask.getCachedPackageInfo(editorInfo.packageName);
|
||||||
if (null == mTargetApplicationInfo) {
|
mAppWorkAroundsUtils.setPackageInfo(packageInfo);
|
||||||
new TargetApplicationGetter(this /* context */, this /* listener */)
|
if (null == packageInfo) {
|
||||||
|
new TargetPackageInfoGetterTask(this /* context */, this /* listener */)
|
||||||
.execute(editorInfo.packageName);
|
.execute(editorInfo.packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -819,10 +820,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
|
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback for the TargetApplicationGetter
|
// Callback for the TargetPackageInfoGetterTask
|
||||||
@Override
|
@Override
|
||||||
public void onTargetApplicationKnown(final ApplicationInfo info) {
|
public void onTargetPackageInfoKnown(final PackageInfo info) {
|
||||||
mTargetApplicationInfo = info;
|
mAppWorkAroundsUtils.setPackageInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1369,8 +1370,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Constants.CODE_ENTER == code && mTargetApplicationInfo != null
|
if (Constants.CODE_ENTER == code && mAppWorkAroundsUtils.isBeforeJellyBean()) {
|
||||||
&& mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
|
|
||||||
// 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
|
||||||
|
@ -1864,8 +1864,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
// 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 (mTargetApplicationInfo != null
|
if (mAppWorkAroundsUtils.isBeforeJellyBean()) {
|
||||||
&& mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
|
|
||||||
// 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
|
||||||
|
@ -2785,12 +2784,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
|
|
||||||
public void debugDumpStateAndCrashWithException(final String context) {
|
public void debugDumpStateAndCrashWithException(final String context) {
|
||||||
final StringBuilder s = new StringBuilder();
|
final StringBuilder s = new StringBuilder(mAppWorkAroundsUtils.toString());
|
||||||
s.append("Target application : ").append(mTargetApplicationInfo.name)
|
s.append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes)
|
||||||
.append("\nPackage : ").append(mTargetApplicationInfo.packageName)
|
|
||||||
.append("\nTarget app sdk version : ")
|
|
||||||
.append(mTargetApplicationInfo.targetSdkVersion)
|
|
||||||
.append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes)
|
|
||||||
.append("\nContext : ").append(context);
|
.append("\nContext : ").append(context);
|
||||||
throw new RuntimeException(s.toString());
|
throw new RuntimeException(s.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,54 +17,54 @@
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.util.LruCache;
|
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 final int MAX_CACHE_ENTRIES = 64; // arbitrary
|
||||||
private static LruCache<String, ApplicationInfo> sCache =
|
private static final LruCache<String, PackageInfo> sCache =
|
||||||
new LruCache<String, ApplicationInfo>(MAX_CACHE_ENTRIES);
|
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;
|
if (null == packageName) return null;
|
||||||
return sCache.get(packageName);
|
return sCache.get(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeApplicationInfoCache(final String packageName) {
|
public static void removeCachedPackageInfo(final String packageName) {
|
||||||
sCache.remove(packageName);
|
sCache.remove(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnTargetApplicationKnownListener {
|
public interface OnTargetPackageInfoKnownListener {
|
||||||
public void onTargetApplicationKnown(final ApplicationInfo info);
|
public void onTargetPackageInfoKnown(final PackageInfo info);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private final OnTargetApplicationKnownListener mListener;
|
private final OnTargetPackageInfoKnownListener mListener;
|
||||||
|
|
||||||
public TargetApplicationGetter(final Context context,
|
public TargetPackageInfoGetterTask(final Context context,
|
||||||
final OnTargetApplicationKnownListener listener) {
|
final OnTargetPackageInfoKnownListener listener) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ApplicationInfo doInBackground(final String... packageName) {
|
protected PackageInfo doInBackground(final String... packageName) {
|
||||||
final PackageManager pm = mContext.getPackageManager();
|
final PackageManager pm = mContext.getPackageManager();
|
||||||
mContext = null; // Bazooka-powered anti-leak device
|
mContext = null; // Bazooka-powered anti-leak device
|
||||||
try {
|
try {
|
||||||
final ApplicationInfo targetAppInfo =
|
final PackageInfo packageInfo = pm.getPackageInfo(packageName[0], 0 /* flags */);
|
||||||
pm.getApplicationInfo(packageName[0], 0 /* flags */);
|
sCache.put(packageName[0], packageInfo);
|
||||||
sCache.put(packageName[0], targetAppInfo);
|
return packageInfo;
|
||||||
return targetAppInfo;
|
|
||||||
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
|
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(final ApplicationInfo info) {
|
protected void onPostExecute(final PackageInfo info) {
|
||||||
mListener.onTargetApplicationKnown(info);
|
mListener.onTargetPackageInfoKnown(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue