diff options
Diffstat (limited to 'java/src/com/android/inputmethod')
5 files changed, 72 insertions, 32 deletions
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 013f9220a..c450a1d4f 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import android.text.TextUtils; +import android.util.Log; import android.util.SparseArray; import com.android.inputmethod.annotations.UsedForTesting; @@ -29,6 +30,7 @@ import com.android.inputmethod.latin.makedict.UnsupportedFormatException; import com.android.inputmethod.latin.makedict.WordProperty; import com.android.inputmethod.latin.settings.NativeSuggestOptions; import com.android.inputmethod.latin.utils.CollectionUtils; +import com.android.inputmethod.latin.utils.FileUtils; import com.android.inputmethod.latin.utils.JniUtils; import com.android.inputmethod.latin.utils.LanguageModelParam; import com.android.inputmethod.latin.utils.StringUtils; @@ -84,6 +86,7 @@ public final class BinaryDictionary extends Dictionary { private final Locale mLocale; private final long mDictSize; private final String mDictFilePath; + private final boolean mIsUpdatable; private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH]; private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS]; private final int[] mSpaceIndices = new int[MAX_RESULTS]; @@ -130,6 +133,7 @@ public final class BinaryDictionary extends Dictionary { mLocale = locale; mDictSize = length; mDictFilePath = filename; + mIsUpdatable = isUpdatable; mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance); loadDictionary(filename, offset, length, isUpdatable); } @@ -177,6 +181,7 @@ public final class BinaryDictionary extends Dictionary { int bigramProbability); private static native int setCurrentTimeForTestNative(int currentTime); private static native String getPropertyNative(long dict, String query); + private static native boolean isCorruptedNative(long dict); public static boolean createEmptyDictFile(final String filePath, final long dictVersion, final Locale locale, final Map<String, String> attributeMap) { @@ -198,6 +203,22 @@ public final class BinaryDictionary extends Dictionary { mNativeDict = openNative(path, startOffset, length, isUpdatable); } + // TODO: Check isCorrupted() for main dictionaries. + public boolean isCorrupted() { + if (!isValidDictionary()) { + return false; + } + if (!isCorruptedNative(mNativeDict)) { + return false; + } + // TODO: Record the corruption. + Log.e(TAG, "BinaryDictionary (" + mDictFilePath + ") is corrupted."); + Log.e(TAG, "locale: " + mLocale); + Log.e(TAG, "dict size: " + mDictSize); + Log.e(TAG, "updatable: " + mIsUpdatable); + return true; + } + @UsedForTesting public DictionaryHeader getHeader() throws UnsupportedFormatException { if (mNativeDict == 0) { @@ -444,7 +465,7 @@ public final class BinaryDictionary extends Dictionary { // only be called for actual files. Right now it's only called by the flush() family of // functions, which require an updatable dictionary, so it's okay. But beware. loadDictionary(dictFile.getAbsolutePath(), 0 /* startOffset */, - dictFile.length(), true /* isUpdatable */); + dictFile.length(), mIsUpdatable); } public void flush() { diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index 230739d6f..f9ab9419b 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -276,22 +276,26 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return attributeMap; } + private void removeBinaryDictionaryLocked() { + if (mBinaryDictionary != null) { + mBinaryDictionary.close(); + } + if (mDictFile.exists() && !FileUtils.deleteRecursively(mDictFile)) { + Log.e(TAG, "Can't remove a file: " + mDictFile.getName()); + } + mBinaryDictionary = null; + } + protected void clear() { - final File dictFile = mDictFile; getExecutor(mDictName).execute(new Runnable() { @Override public void run() { if (mDictionaryWriter == null) { - if (mBinaryDictionary != null) { - mBinaryDictionary.close(); - } - if (dictFile.exists() && !FileUtils.deleteRecursively(dictFile)) { - Log.e(TAG, "Can't remove a file: " + dictFile.getName()); - } - BinaryDictionary.createEmptyDictFile(dictFile.getAbsolutePath(), + removeBinaryDictionaryLocked(); + BinaryDictionary.createEmptyDictFile(mDictFile.getAbsolutePath(), DICTIONARY_FORMAT_VERSION, mLocale, getHeaderAttributeMap()); mBinaryDictionary = new BinaryDictionary( - dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), + mDictFile.getAbsolutePath(), 0 /* offset */, mDictFile.length(), true /* useFullEditDistance */, mLocale, mDictType, mIsUpdatable); } else { mDictionaryWriter.clear(); @@ -469,6 +473,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { proximityInfo, blockOffensiveWords, additionalFeaturesOptions, sessionId); holder.set(binarySuggestion); + if (mBinaryDictionary.isCorrupted()) { + removeBinaryDictionaryLocked(); + } } }); return holder.get(null, TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS); diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index eeb5bf536..045d06f0e 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -490,6 +490,7 @@ public final class InputLogic { handler.showGesturePreviewAndSuggestionStrip( SuggestedWords.EMPTY, false /* dismissGestureFloatingPreviewText */); handler.cancelUpdateSuggestionStrip(); + ++mAutoCommitSequenceNumber; mConnection.beginBatchEdit(); if (mWordComposer.isComposingWord()) { if (settingsValues.mIsInternal) { @@ -587,6 +588,7 @@ public final class InputLogic { public void onEndBatchInput(final SettingsValues settingValues, final InputPointers batchPointers) { mInputLogicHandler.onEndBatchInput(batchPointers, mAutoCommitSequenceNumber); + ++mAutoCommitSequenceNumber; } // TODO: remove this argument diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java index 71e120c5f..bf776cfc5 100644 --- a/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java @@ -120,16 +120,10 @@ public class Ver2DictDecoder extends AbstractDictDecoder { // used only for testing. private final DictionaryBufferFactory mBufferFactory; protected DictBuffer mDictBuffer; - private final BinaryDictionary mBinaryDictionary; /* package */ Ver2DictDecoder(final File file, final int factoryFlag) { mDictionaryBinaryFile = file; mDictBuffer = null; - // dictType is not being used in dicttool. Passing an empty string. - mBinaryDictionary = new BinaryDictionary(file.getAbsolutePath(), - 0 /* offset */, file.length() /* length */, true /* useFullEditDistance */, - null /* locale */, "" /* dictType */, false /* isUpdatable */); - if ((factoryFlag & MASK_DICTBUFFER) == USE_READONLY_BYTEBUFFER) { mBufferFactory = new DictionaryBufferFromReadOnlyByteBufferFactory(); } else if ((factoryFlag & MASK_DICTBUFFER) == USE_BYTEARRAY) { @@ -144,10 +138,6 @@ public class Ver2DictDecoder extends AbstractDictDecoder { /* package */ Ver2DictDecoder(final File file, final DictionaryBufferFactory factory) { mDictionaryBinaryFile = file; mBufferFactory = factory; - // dictType is not being used in dicttool. Passing an empty string. - mBinaryDictionary = new BinaryDictionary(file.getAbsolutePath(), - 0 /* offset */, file.length() /* length */, true /* useFullEditDistance */, - null /* locale */, "" /* dictType */, false /* isUpdatable */); } @Override @@ -172,7 +162,13 @@ public class Ver2DictDecoder extends AbstractDictDecoder { @Override public DictionaryHeader readHeader() throws IOException, UnsupportedFormatException { - final DictionaryHeader header = mBinaryDictionary.getHeader(); + // dictType is not being used in dicttool. Passing an empty string. + final BinaryDictionary binaryDictionary = new BinaryDictionary( + mDictionaryBinaryFile.getAbsolutePath(), 0 /* offset */, + mDictionaryBinaryFile.length() /* length */, true /* useFullEditDistance */, + null /* locale */, "" /* dictType */, false /* isUpdatable */); + final DictionaryHeader header = binaryDictionary.getHeader(); + binaryDictionary.close(); if (header == null) { throw new IOException("Cannot read the dictionary header."); } @@ -254,6 +250,11 @@ public class Ver2DictDecoder extends AbstractDictDecoder { @Override public FusionDictionary readDictionaryBinary(final boolean deleteDictIfBroken) throws FileNotFoundException, IOException, UnsupportedFormatException { + // dictType is not being used in dicttool. Passing an empty string. + final BinaryDictionary binaryDictionary = new BinaryDictionary( + mDictionaryBinaryFile.getAbsolutePath(), 0 /* offset */, + mDictionaryBinaryFile.length() /* length */, true /* useFullEditDistance */, + null /* locale */, "" /* dictType */, false /* isUpdatable */); final DictionaryHeader header = readHeader(); final FusionDictionary fusionDict = new FusionDictionary(new FusionDictionary.PtNodeArray(), header.mDictionaryOptions); @@ -261,11 +262,11 @@ public class Ver2DictDecoder extends AbstractDictDecoder { final ArrayList<WordProperty> wordProperties = CollectionUtils.newArrayList(); do { final BinaryDictionary.GetNextWordPropertyResult result = - mBinaryDictionary.getNextWordProperty(token); + binaryDictionary.getNextWordProperty(token); final WordProperty wordProperty = result.mWordProperty; if (wordProperty == null) { + binaryDictionary.close(); if (deleteDictIfBroken) { - mBinaryDictionary.close(); mDictionaryBinaryFile.delete(); } return null; @@ -294,6 +295,7 @@ public class Ver2DictDecoder extends AbstractDictDecoder { fusionDict.setBigram(word0, bigram.mWord, bigram.mProbabilityInfo); } } + binaryDictionary.close(); return fusionDict; } diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java index 88fff38f2..afe82317e 100644 --- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java @@ -35,7 +35,6 @@ public class Ver4DictDecoder extends AbstractDictDecoder { private static final String TAG = Ver4DictDecoder.class.getSimpleName(); final File mDictDirectory; - final BinaryDictionary mBinaryDictionary; @UsedForTesting /* package */ Ver4DictDecoder(final File dictDirectory, final int factoryFlag) { @@ -45,24 +44,32 @@ public class Ver4DictDecoder extends AbstractDictDecoder { @UsedForTesting /* package */ Ver4DictDecoder(final File dictDirectory, final DictionaryBufferFactory factory) { mDictDirectory = dictDirectory; - // dictType is not being used in dicttool. Passing an empty string. - mBinaryDictionary = new BinaryDictionary(dictDirectory.getAbsolutePath(), - 0 /* offset */, 0 /* length */, true /* useFullEditDistance */, null /* locale */, - "" /* dictType */, true /* isUpdatable */); + } @Override public DictionaryHeader readHeader() throws IOException, UnsupportedFormatException { - final DictionaryHeader header = mBinaryDictionary.getHeader(); + // dictType is not being used in dicttool. Passing an empty string. + final BinaryDictionary binaryDictionary= new BinaryDictionary( + mDictDirectory.getAbsolutePath(), 0 /* offset */, 0 /* length */, + true /* useFullEditDistance */, null /* locale */, + "" /* dictType */, true /* isUpdatable */); + final DictionaryHeader header = binaryDictionary.getHeader(); + binaryDictionary.close(); if (header == null) { throw new IOException("Cannot read the dictionary header."); } - return mBinaryDictionary.getHeader(); + return header; } @Override public FusionDictionary readDictionaryBinary(final boolean deleteDictIfBroken) throws FileNotFoundException, IOException, UnsupportedFormatException { + // dictType is not being used in dicttool. Passing an empty string. + final BinaryDictionary binaryDictionary = new BinaryDictionary( + mDictDirectory.getAbsolutePath(), 0 /* offset */, 0 /* length */, + true /* useFullEditDistance */, null /* locale */, + "" /* dictType */, true /* isUpdatable */); final DictionaryHeader header = readHeader(); final FusionDictionary fusionDict = new FusionDictionary(new FusionDictionary.PtNodeArray(), header.mDictionaryOptions); @@ -70,11 +77,11 @@ public class Ver4DictDecoder extends AbstractDictDecoder { final ArrayList<WordProperty> wordProperties = CollectionUtils.newArrayList(); do { final BinaryDictionary.GetNextWordPropertyResult result = - mBinaryDictionary.getNextWordProperty(token); + binaryDictionary.getNextWordProperty(token); final WordProperty wordProperty = result.mWordProperty; if (wordProperty == null) { + binaryDictionary.close(); if (deleteDictIfBroken) { - mBinaryDictionary.close(); FileUtils.deleteRecursively(mDictDirectory); } return null; @@ -103,6 +110,7 @@ public class Ver4DictDecoder extends AbstractDictDecoder { fusionDict.setBigram(word0, bigram.mWord, bigram.mProbabilityInfo); } } + binaryDictionary.close(); return fusionDict; } } |