Loading java/src/com/android/inputmethod/latin/BinaryDictionary.java +22 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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]; Loading Loading @@ -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); } Loading Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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() { Loading java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +16 −9 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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); Loading native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -529,6 +529,14 @@ static int latinime_BinaryDictionary_setCurrentTimeForTest(JNIEnv *env, jclass c return TimeKeeper::peekCurrentTime(); } static bool latinime_BinaryDictionary_isCorruptedNative(JNIEnv *env, jclass clazz, jlong dict) { Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict); if (!dictionary) { return false; } return dictionary->getDictionaryStructurePolicy()->isCorrupted(); } static const JNINativeMethod sMethods[] = { { const_cast<char *>("createEmptyDictFileNative"), Loading Loading @@ -642,6 +650,11 @@ static const JNINativeMethod sMethods[] = { const_cast<char *>("getPropertyNative"), const_cast<char *>("(JLjava/lang/String;)Ljava/lang/String;"), reinterpret_cast<void *>(latinime_BinaryDictionary_getProperty) }, { const_cast<char *>("isCorruptedNative"), const_cast<char *>("(J)Z"), reinterpret_cast<void *>(latinime_BinaryDictionary_isCorruptedNative) } }; Loading Loading
java/src/com/android/inputmethod/latin/BinaryDictionary.java +22 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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]; Loading Loading @@ -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); } Loading Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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() { Loading
java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +16 −9 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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); Loading
native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -529,6 +529,14 @@ static int latinime_BinaryDictionary_setCurrentTimeForTest(JNIEnv *env, jclass c return TimeKeeper::peekCurrentTime(); } static bool latinime_BinaryDictionary_isCorruptedNative(JNIEnv *env, jclass clazz, jlong dict) { Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict); if (!dictionary) { return false; } return dictionary->getDictionaryStructurePolicy()->isCorrupted(); } static const JNINativeMethod sMethods[] = { { const_cast<char *>("createEmptyDictFileNative"), Loading Loading @@ -642,6 +650,11 @@ static const JNINativeMethod sMethods[] = { const_cast<char *>("getPropertyNative"), const_cast<char *>("(JLjava/lang/String;)Ljava/lang/String;"), reinterpret_cast<void *>(latinime_BinaryDictionary_getProperty) }, { const_cast<char *>("isCorruptedNative"), const_cast<char *>("(J)Z"), reinterpret_cast<void *>(latinime_BinaryDictionary_isCorruptedNative) } }; Loading