diff options
Diffstat (limited to 'java/src')
8 files changed, 109 insertions, 51 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java index 3cfef972a..8bc789317 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java @@ -29,7 +29,6 @@ import android.util.Log; import android.util.SparseArray; import android.view.MotionEvent; import android.view.View; -import android.view.ViewParent; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.accessibility.AccessibilityEvent; import android.view.inputmethod.EditorInfo; @@ -276,18 +275,7 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat */ void sendAccessibilityEventForKey(Key key, int eventType) { final AccessibilityEvent event = createAccessibilityEvent(key, eventType); - final ViewParent parent = mKeyboardView.getParent(); - - if (parent == null) { - return; - } - - if (!parent.requestSendAccessibilityEvent(mKeyboardView, event)) { - // TODO: Remove this line after the top-level view for the IME - // window is fixed to be non-null and requestSendAccessibilityEvent - // can return true. - mAccessibilityUtils.requestSendAccessibilityEvent(event); - } + mAccessibilityUtils.requestSendAccessibilityEvent(event); } /** diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index 5ea28abe2..9d8bace71 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -42,6 +42,8 @@ public class ProximityInfo { private final int mKeyboardMinWidth; private final int mKeyboardHeight; private final int mMostCommonKeyWidth; + private final Key[] mKeys; + private final TouchPositionCorrection mTouchPositionCorrection; private final Key[][] mGridNeighbors; private final String mLocaleStr; @@ -62,13 +64,36 @@ public class ProximityInfo { mKeyboardHeight = height; mKeyHeight = mostCommonKeyHeight; mMostCommonKeyWidth = mostCommonKeyWidth; + mKeys = keys; + mTouchPositionCorrection = touchPositionCorrection; mGridNeighbors = new Key[mGridSize][]; if (minWidth == 0 || height == 0) { // No proximity required. Keyboard might be more keys keyboard. return; } - computeNearestNeighbors( - mostCommonKeyWidth, keys, touchPositionCorrection); + computeNearestNeighbors(); + mNativeProximityInfo = createNativeProximityInfo(); + } + + // TODO: Remove this public constructor when the native part of the ProximityInfo becomes + // immutable. + // This public constructor aims only for test purpose. + public ProximityInfo(ProximityInfo o) { + mLocaleStr = o.mLocaleStr; + mGridWidth = o.mGridWidth; + mGridHeight = o.mGridHeight; + mGridSize = o.mGridSize; + mCellWidth = o.mCellWidth; + mCellHeight = o.mCellHeight; + mKeyboardMinWidth = o.mKeyboardMinWidth; + mKeyboardHeight = o.mKeyboardHeight; + mKeyHeight = o.mKeyHeight; + mMostCommonKeyWidth = o.mMostCommonKeyWidth; + mKeys = o.mKeys; + mTouchPositionCorrection = o.mTouchPositionCorrection; + mGridNeighbors = new Key[mGridSize][]; + computeNearestNeighbors(); + mNativeProximityInfo = createNativeProximityInfo(); } public static ProximityInfo createDummyProximityInfo() { @@ -100,8 +125,12 @@ public class ProximityInfo { private native void releaseProximityInfoNative(long nativeProximityInfo); - private final void setProximityInfo(Key[][] gridNeighborKeys, int keyboardWidth, - int keyboardHeight, final Key[] keys, TouchPositionCorrection touchPositionCorrection) { + private final long createNativeProximityInfo() { + final Key[][] gridNeighborKeys = mGridNeighbors; + final int keyboardWidth = mKeyboardMinWidth; + final int keyboardHeight = mKeyboardHeight; + final Key[] keys = mKeys; + final TouchPositionCorrection touchPositionCorrection = mTouchPositionCorrection; final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE]; Arrays.fill(proximityCharsArray, KeyDetector.NOT_A_CODE); for (int i = 0; i < mGridSize; ++i) { @@ -156,7 +185,7 @@ public class ProximityInfo { sweetSpotCenterXs = sweetSpotCenterYs = sweetSpotRadii = null; } - mNativeProximityInfo = setProximityInfoNative(mLocaleStr, MAX_PROXIMITY_CHARS_SIZE, + return setProximityInfoNative(mLocaleStr, MAX_PROXIMITY_CHARS_SIZE, keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, mMostCommonKeyWidth, proximityCharsArray, keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes, @@ -179,8 +208,9 @@ public class ProximityInfo { } } - private void computeNearestNeighbors(int defaultWidth, final Key[] keys, - TouchPositionCorrection touchPositionCorrection) { + private void computeNearestNeighbors() { + final int defaultWidth = mMostCommonKeyWidth; + final Key[] keys = mKeys; final HashMap<Integer, Key> keyCodeMap = new HashMap<Integer, Key>(); for (final Key key : keys) { keyCodeMap.put(key.mCode, key); @@ -206,8 +236,6 @@ public class ProximityInfo { Arrays.copyOfRange(neighborKeys, 0, count); } } - setProximityInfo(mGridNeighbors, mKeyboardMinWidth, mKeyboardHeight, keys, - touchPositionCorrection); } public void fillArrayWithNearestKeyCodes(int x, int y, int primaryKeyCode, int[] dest) { diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java index f0076a5b6..ffdbfbb67 100644 --- a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java +++ b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java @@ -22,6 +22,7 @@ import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOAR import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; import android.os.Build; +import android.text.TextUtils; import android.view.inputmethod.InputMethodSubtype; import java.util.ArrayList; @@ -84,11 +85,14 @@ public class AdditionalSubtype { } public static InputMethodSubtype[] createAdditionalSubtypesArray(String prefSubtypes) { + if (TextUtils.isEmpty(prefSubtypes)) { + return null; + } final String[] prefSubtypeArray = prefSubtypes.split(PREF_SUBTYPE_SEPARATOR); final ArrayList<InputMethodSubtype> subtypesList = new ArrayList<InputMethodSubtype>(prefSubtypeArray.length); - for (int i = 0; i < prefSubtypeArray.length; i++) { - final InputMethodSubtype subtype = createAdditionalSubtype(prefSubtypeArray[i]); + for (final String prefSubtype : prefSubtypeArray) { + final InputMethodSubtype subtype = createAdditionalSubtype(prefSubtype); if (subtype.getNameResId() == SubtypeLocale.UNKNOWN_KEYBOARD_LAYOUT) { // Skip unknown keyboard layout subtype. This may happen when predefined keyboard // layout has been removed. diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index a4670daf2..37eced5d6 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -58,6 +58,9 @@ public class BinaryDictionaryFileDumper { public static final String QUERY_PARAMETER_MAY_PROMPT_USER = "mayPrompt"; public static final String QUERY_PARAMETER_TRUE = "true"; + public static final String QUERY_PARAMETER_DELETE_RESULT = "result"; + public static final String QUERY_PARAMETER_SUCCESS = "success"; + public static final String QUERY_PARAMETER_FAILURE = "failure"; // Prevents this class to be accidentally instantiated. private BinaryDictionaryFileDumper() { @@ -145,7 +148,7 @@ public class BinaryDictionaryFileDumper { final int MODE_MIN = COMPRESSED_CRYPTED_COMPRESSED; final int MODE_MAX = NONE; - final Uri wordListUri = getProviderUriBuilder(id).build(); + final Uri.Builder wordListUriBuilder = getProviderUriBuilder(id); final String outputFileName = BinaryDictionaryGetter.getCacheFileName(id, locale, context); for (int mode = MODE_MIN; mode <= MODE_MAX; ++mode) { @@ -154,6 +157,7 @@ public class BinaryDictionaryFileDumper { File outputFile = null; FileOutputStream outputStream = null; AssetFileDescriptor afd = null; + final Uri wordListUri = wordListUriBuilder.build(); try { // Open input. afd = openAssetFileDescriptor(resolver, wordListUri); @@ -190,9 +194,12 @@ public class BinaryDictionaryFileDumper { break; } checkMagicAndCopyFileTo(new BufferedInputStream(inputStream), outputStream); - if (0 >= resolver.delete(wordListUri, null, null)) { + wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT, + QUERY_PARAMETER_SUCCESS); + if (0 >= resolver.delete(wordListUriBuilder.build(), null, null)) { Log.e(TAG, "Could not have the dictionary pack delete a word list"); } + BinaryDictionaryGetter.removeFilesWithIdExcept(context, id, outputFile); // Success! Close files (through the finally{} clause) and return. return AssetFileAddress.makeFromFileName(outputFileName); } catch (Exception e) { @@ -225,9 +232,11 @@ public class BinaryDictionaryFileDumper { // We could not copy the file at all. This is very unexpected. // I'd rather not print the word list ID to the log out of security concerns Log.e(TAG, "Could not copy a word list. Will not be able to use it."); - // If we can't copy it we should probably delete it to avoid trying to copy it over - // and over each time we open LatinIME. - if (0 >= resolver.delete(wordListUri, null, null)) { + // If we can't copy it we should warn the dictionary provider so that it can mark it + // as invalid. + wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT, + QUERY_PARAMETER_FAILURE); + if (0 >= resolver.delete(wordListUriBuilder.build(), null, null)) { Log.e(TAG, "In addition, we were unable to delete it."); } return null; diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 5acd62904..063243e1b 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -283,6 +283,39 @@ class BinaryDictionaryGetter { } /** + * Remove all files with the passed id, except the passed file. + * + * If a dictionary with a given ID has a metadata change that causes it to change + * path, we need to remove the old version. The only way to do this is to check all + * installed files for a matching ID in a different directory. + */ + public static void removeFilesWithIdExcept(final Context context, final String id, + final File fileToKeep) { + try { + final File canonicalFileToKeep = fileToKeep.getCanonicalFile(); + final File[] directoryList = getCachedDirectoryList(context); + if (null == directoryList) return; + for (File directory : directoryList) { + // There is one directory per locale. See #getCachedDirectoryList + if (!directory.isDirectory()) continue; + final File[] wordLists = directory.listFiles(); + if (null == wordLists) continue; + for (File wordList : wordLists) { + final String fileId = getWordListIdFromFileName(wordList.getName()); + if (fileId.equals(id)) { + if (!canonicalFileToKeep.equals(wordList.getCanonicalFile())) { + wordList.delete(); + } + } + } + } + } catch (java.io.IOException e) { + Log.e(TAG, "IOException trying to cleanup files : " + e); + } + } + + + /** * Returns the id associated with the main word list for a specified locale. * * Word lists stored in Android Keyboard's resources are referred to as the "main" diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java index 4b77473d9..0a09c845e 100644 --- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java @@ -149,7 +149,11 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { final Cursor cursor = mContext.getContentResolver().query( Contacts.CONTENT_URI, PROJECTION_ID_ONLY, null, null, null); if (cursor != null) { - return cursor.getCount(); + try { + return cursor.getCount(); + } finally { + cursor.close(); + } } return 0; } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index b474a8558..83658f77e 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -2291,6 +2291,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen break; } } + + if (Keyboard.CODE_DELETE == primaryCode) { + // This is a stopgap solution to avoid leaving a high surrogate alone in a text view. + // In the future, we need to deprecate deteleSurroundingText() and have a surrogate + // pair-friendly way of deleting characters in InputConnection. + final InputConnection ic = getCurrentInputConnection(); + if (null != ic) { + final CharSequence lastChar = ic.getTextBeforeCursor(1, 0); + if (!TextUtils.isEmpty(lastChar) && Character.isHighSurrogate(lastChar.charAt(0))) { + ic.deleteSurroundingText(1, 0); + } + } + } } // receive ringer mode change and network state change. diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 9e478fab4..c98a27b64 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -503,27 +503,6 @@ public class Suggest implements Dictionary.WordCallback { return true; } - // TODO: Use codepoint instead of char - private int searchBigramSuggestion(final char[] word, final int offset, final int length) { - // TODO This is almost O(n^2). Might need fix. - // search whether the word appeared in bigram data - int bigramSuggestSize = mBigramSuggestions.size(); - for (int i = 0; i < bigramSuggestSize; i++) { - if (mBigramSuggestions.get(i).codePointCount() == length) { - boolean chk = true; - for (int j = 0; j < length; j++) { - if (mBigramSuggestions.get(i).codePointAt(j) != word[offset+j]) { - chk = false; - break; - } - } - if (chk) return i; - } - } - - return -1; - } - public void close() { final HashSet<Dictionary> dictionaries = new HashSet<Dictionary>(); dictionaries.addAll(mUnigramDictionaries.values()); |