aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java18
-rw-r--r--native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp33
-rw-r--r--native/src/binary_format.h13
3 files changed, 55 insertions, 9 deletions
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index a35b0f5b0..f0637b8ce 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -56,8 +56,11 @@ public class DictionaryFactory {
BinaryDictionaryGetter.getDictionaryFiles(locale, context, fallbackResId);
if (null != assetFileList) {
for (final AssetFileAddress f : assetFileList) {
- dictList.add(
- new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null));
+ final BinaryDictionary binaryDictionary =
+ new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null);
+ if (binaryDictionary.isValidDictionary()) {
+ dictList.add(binaryDictionary);
+ }
}
}
@@ -67,7 +70,16 @@ public class DictionaryFactory {
if (null == dictList) {
return new DictionaryCollection();
} else {
- return new DictionaryCollection(dictList);
+ if (dictList.isEmpty()) {
+ // The list may be empty if no dictionaries have been added. The getter should not
+ // return an empty list, but if it does we end up here. Likewise, if the files
+ // we found could not be opened by the native code for any reason (format mismatch,
+ // file too big to fit in memory, etc) then we could have an empty list. In this
+ // case we want to fall back on the resource.
+ return new DictionaryCollection(createBinaryDictionary(context, fallbackResId));
+ } else {
+ return new DictionaryCollection(dictList);
+ }
}
}
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index ce874d8d4..18c972444 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "LatinIME: jni: BinaryDictionary"
+#include "binary_format.h"
#include "com_android_inputmethod_latin_BinaryDictionary.h"
#include "dictionary.h"
#include "jni.h"
@@ -38,6 +39,8 @@
namespace latinime {
+void releaseDictBuf(void* dictBuf, const size_t length, int fd);
+
static jint latinime_BinaryDictionary_open(JNIEnv *env, jobject object,
jstring sourceDir, jlong dictOffset, jlong dictSize,
jint typedLetterMultiplier, jint fullWordMultiplier, jint maxWordLength, jint maxWords,
@@ -104,8 +107,18 @@ static jint latinime_BinaryDictionary_open(JNIEnv *env, jobject object,
LOGE("DICT: dictBuf is null");
return 0;
}
- Dictionary *dictionary = new Dictionary(dictBuf, dictSize, fd, adjust, typedLetterMultiplier,
- fullWordMultiplier, maxWordLength, maxWords, maxAlternatives);
+ Dictionary *dictionary = NULL;
+ if (BinaryFormat::UNKNOWN_FORMAT == BinaryFormat::detectFormat((uint8_t*)dictBuf)) {
+ LOGE("DICT: dictionary format is unknown, bad magic number");
+#ifdef USE_MMAP_FOR_DICTIONARY
+ releaseDictBuf(((char*)dictBuf) - adjust, adjDictSize, fd);
+#else // USE_MMAP_FOR_DICTIONARY
+ releaseDictBuf(dictBuf, 0, 0);
+#endif // USE_MMAP_FOR_DICTIONARY
+ } else {
+ dictionary = new Dictionary(dictBuf, dictSize, fd, adjust, typedLetterMultiplier,
+ fullWordMultiplier, maxWordLength, maxWords, maxAlternatives);
+ }
PROF_END(66);
PROF_CLOSE;
return (jint)dictionary;
@@ -180,19 +193,27 @@ static void latinime_BinaryDictionary_close(JNIEnv *env, jobject object, jint di
void *dictBuf = dictionary->getDict();
if (!dictBuf) return;
#ifdef USE_MMAP_FOR_DICTIONARY
- int ret = munmap((void *)((char *)dictBuf - dictionary->getDictBufAdjust()),
- dictionary->getDictSize() + dictionary->getDictBufAdjust());
+ releaseDictBuf((void *)((char *)dictBuf - dictionary->getDictBufAdjust()),
+ dictionary->getDictSize() + dictionary->getDictBufAdjust(), dictionary->getMmapFd());
+#else // USE_MMAP_FOR_DICTIONARY
+ releaseDictBuf(dictBuf, 0, 0);
+#endif // USE_MMAP_FOR_DICTIONARY
+ delete dictionary;
+}
+
+void releaseDictBuf(void* dictBuf, const size_t length, int fd) {
+#ifdef USE_MMAP_FOR_DICTIONARY
+ int ret = munmap(dictBuf, length);
if (ret != 0) {
LOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
}
- ret = close(dictionary->getMmapFd());
+ ret = close(fd);
if (ret != 0) {
LOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
}
#else // USE_MMAP_FOR_DICTIONARY
free(dictBuf);
#endif // USE_MMAP_FOR_DICTIONARY
- delete dictionary;
}
static JNINativeMethod sMethods[] = {
diff --git a/native/src/binary_format.h b/native/src/binary_format.h
index e9f108e25..7deec27d3 100644
--- a/native/src/binary_format.h
+++ b/native/src/binary_format.h
@@ -17,6 +17,8 @@
#ifndef LATINIME_BINARY_FORMAT_H
#define LATINIME_BINARY_FORMAT_H
+#include "unigram_dictionary.h"
+
namespace latinime {
class BinaryFormat {
@@ -26,6 +28,11 @@ private:
const static int MULTIPLE_BYTE_CHARACTER_ADDITIONAL_SIZE = 2;
public:
+ const static int UNKNOWN_FORMAT = -1;
+ const static int FORMAT_VERSION_1 = 1;
+ const static uint16_t FORMAT_VERSION_1_MAGIC_NUMBER = 0x78B1;
+
+ static int detectFormat(const uint8_t* const dict);
static int getGroupCountAndForwardPointer(const uint8_t* const dict, int* pos);
static uint8_t getFlagsAndForwardPointer(const uint8_t* const dict, int* pos);
static int32_t getCharCodeAndForwardPointer(const uint8_t* const dict, int* pos);
@@ -43,6 +50,12 @@ public:
int *pos);
};
+inline int BinaryFormat::detectFormat(const uint8_t* const dict) {
+ const uint16_t magicNumber = (dict[0] << 8) + dict[1]; // big endian
+ if (FORMAT_VERSION_1_MAGIC_NUMBER == magicNumber) return FORMAT_VERSION_1;
+ return UNKNOWN_FORMAT;
+}
+
inline int BinaryFormat::getGroupCountAndForwardPointer(const uint8_t* const dict, int* pos) {
return dict[(*pos)++];
}