Loading java/src/com/android/inputmethod/compat/AppWorkaroundsUtils.java 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * 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(); } } java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java +1 −1 Original line number Diff line number Diff line Loading @@ -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); Loading java/src/com/android/inputmethod/latin/LatinIME.java +16 −21 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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()); } Loading java/src/com/android/inputmethod/latin/TargetApplicationGetter.java→java/src/com/android/inputmethod/latin/TargetPackageInfoGetterTask.java +18 −18 Original line number Diff line number Diff line Loading @@ -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
java/src/com/android/inputmethod/compat/AppWorkaroundsUtils.java 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * 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(); } }
java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java +1 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
java/src/com/android/inputmethod/latin/LatinIME.java +16 −21 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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()); } Loading
java/src/com/android/inputmethod/latin/TargetApplicationGetter.java→java/src/com/android/inputmethod/latin/TargetPackageInfoGetterTask.java +18 −18 Original line number Diff line number Diff line Loading @@ -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); } }