aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
-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
6 files changed, 71 insertions, 29 deletions
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());