aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java14
-rw-r--r--java/src/com/android/inputmethod/keyboard/ProximityInfo.java46
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtype.java8
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java19
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java33
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java6
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java13
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java21
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());