diff options
-rw-r--r-- | java/src/com/android/inputmethod/deprecated/VoiceProxy.java | 17 | ||||
-rw-r--r-- | java/src/com/android/inputmethod/latin/LatinIME.java | 24 | ||||
-rw-r--r-- | native/src/bigram_dictionary.cpp | 2 | ||||
-rw-r--r-- | native/src/binary_format.h | 47 | ||||
-rw-r--r-- | native/src/defines.h | 3 | ||||
-rw-r--r-- | native/src/dictionary.cpp | 14 | ||||
-rw-r--r-- | native/src/unigram_dictionary.cpp | 3 | ||||
-rw-r--r-- | tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java | 44 |
8 files changed, 97 insertions, 57 deletions
diff --git a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java index 700709d50..c1c6d31cd 100644 --- a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java +++ b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java @@ -92,6 +92,7 @@ public class VoiceProxy implements VoiceInput.UiListener { private static final boolean DEBUG = LatinImeLogger.sDBG; private boolean mAfterVoiceInput; + private boolean mConfigurationChanging; private boolean mHasUsedVoiceInput; private boolean mHasUsedVoiceInputUnsupportedLocale; private boolean mImmediatelyAfterVoiceInput; @@ -159,11 +160,11 @@ public class VoiceProxy implements VoiceInput.UiListener { mPasswordText = isPasswordText; } - public void flushVoiceInputLogs(boolean configurationChanged) { + public void flushVoiceInputLogs() { if (!VOICE_INSTALLED) { return; } - if (!configurationChanged) { + if (!mConfigurationChanging) { if (mAfterVoiceInput) { mVoiceInput.flushAllTextModificationCounters(); mVoiceInput.logInputEnded(); @@ -318,11 +319,11 @@ public class VoiceProxy implements VoiceInput.UiListener { mImmediatelyAfterVoiceInput = false; } - public void hideVoiceWindow(boolean configurationChanging) { + public void hideVoiceWindow() { if (!VOICE_INSTALLED) { return; } - if (!configurationChanging) { + if (!mConfigurationChanging) { if (mAfterVoiceInput) mVoiceInput.logInputEnded(); if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) { @@ -842,4 +843,12 @@ public class VoiceProxy implements VoiceInput.UiListener { SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES, DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES); } + + public void startChangingConfiguration() { + mConfigurationChanging = true; + } + + public void finishChangingConfiguration() { + mConfigurationChanging = false; + } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index cb22b4935..cb2a275e8 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -195,8 +195,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private InputMethodManagerCompatWrapper mImm; private Resources mResources; private SharedPreferences mPrefs; - private KeyboardSwitcher mKeyboardSwitcher; - private SubtypeSwitcher mSubtypeSwitcher; + private final KeyboardSwitcher mKeyboardSwitcher; + private final SubtypeSwitcher mSubtypeSwitcher; private VoiceProxy mVoiceProxy; private boolean mShouldSwitchToLastSubtype = true; @@ -226,9 +226,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private VibratorCompatWrapper mVibrator; - // TODO: Move this flag to VoiceProxy - private boolean mConfigurationChanging; - // Member variables for remembering the current device orientation. private int mDisplayOrientation; @@ -492,6 +489,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } + public LatinIME() { + super(); + mSubtypeSwitcher = SubtypeSwitcher.getInstance(); + mKeyboardSwitcher = KeyboardSwitcher.getInstance(); + } + @Override public void onCreate() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); @@ -506,8 +509,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar super.onCreate(); mImm = InputMethodManagerCompatWrapper.getInstance(); - mSubtypeSwitcher = SubtypeSwitcher.getInstance(); - mKeyboardSwitcher = KeyboardSwitcher.getInstance(); mVibrator = VibratorCompatWrapper.getInstance(this); mHandler.onCreate(); DEBUG = LatinImeLogger.sDBG; @@ -555,7 +556,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Has to be package-visible for unit tests /* package */ void loadSettings() { if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); - if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance(); mSettingsValues = new SettingsValues(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); } @@ -667,10 +667,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mOptionsDialog.dismiss(); } - mConfigurationChanging = true; + mVoiceProxy.startChangingConfiguration(); super.onConfigurationChanged(conf); mVoiceProxy.onConfigurationChanged(conf); - mConfigurationChanging = false; + mVoiceProxy.finishChangingConfiguration(); // This will work only when the subtype is not supported. LanguageSwitcherProxy.onConfigurationChanged(conf); @@ -833,7 +833,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar LatinImeLogger.commit(); - mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); + mVoiceProxy.flushVoiceInputLogs(); KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); if (inputView != null) inputView.closing(); @@ -963,7 +963,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mOptionsDialog.dismiss(); mOptionsDialog = null; } - mVoiceProxy.hideVoiceWindow(mConfigurationChanging); + mVoiceProxy.hideVoiceWindow(); super.hideWindow(); } diff --git a/native/src/bigram_dictionary.cpp b/native/src/bigram_dictionary.cpp index 19b644679..84048d77d 100644 --- a/native/src/bigram_dictionary.cpp +++ b/native/src/bigram_dictionary.cpp @@ -28,7 +28,7 @@ namespace latinime { BigramDictionary::BigramDictionary(const unsigned char *dict, int maxWordLength, int maxAlternatives, const bool isLatestDictVersion, const bool hasBigram, Dictionary *parentDictionary) - : DICT(dict + NEW_DICTIONARY_HEADER_SIZE), MAX_WORD_LENGTH(maxWordLength), + : DICT(dict), MAX_WORD_LENGTH(maxWordLength), MAX_ALTERNATIVES(maxAlternatives), IS_LATEST_DICT_VERSION(isLatestDictVersion), HAS_BIGRAM(hasBigram), mParentDictionary(parentDictionary) { if (DEBUG_DICT) { diff --git a/native/src/binary_format.h b/native/src/binary_format.h index 1d74998f6..ab033ad90 100644 --- a/native/src/binary_format.h +++ b/native/src/binary_format.h @@ -17,6 +17,7 @@ #ifndef LATINIME_BINARY_FORMAT_H #define LATINIME_BINARY_FORMAT_H +#include <limits> #include "unigram_dictionary.h" namespace latinime { @@ -29,10 +30,18 @@ class BinaryFormat { public: const static int UNKNOWN_FORMAT = -1; - const static int FORMAT_VERSION_1 = 1; - const static uint16_t FORMAT_VERSION_1_MAGIC_NUMBER = 0x78B1; + // Originally, format version 1 had a 16-bit magic number, then the version number `01' + // then options that must be 0. Hence the first 32-bits of the format are always as follow + // and it's okay to consider them a magic number as a whole. + const static uint32_t FORMAT_VERSION_1_MAGIC_NUMBER = 0x78B10100; + const static unsigned int FORMAT_VERSION_1_HEADER_SIZE = 5; + // The versions of Latin IME that only handle format version 1 only test for the magic + // number, so we had to change it so that version 2 files would be rejected by older + // implementations. On this occasion, we made the magic number 32 bits long. + const static uint32_t FORMAT_VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; static int detectFormat(const uint8_t* const dict); + static unsigned int getHeaderSize(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); @@ -55,9 +64,37 @@ class BinaryFormat { }; 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; + // The magic number is stored big-endian. + const uint32_t magicNumber = (dict[0] << 24) + (dict[1] << 16) + (dict[2] << 8) + dict[3]; + switch (magicNumber) { + case FORMAT_VERSION_1_MAGIC_NUMBER: + // Format 1 header is exactly 5 bytes long and looks like: + // Magic number (2 bytes) 0x78 0xB1 + // Version number (1 byte) 0x01 + // Options (2 bytes) must be 0x00 0x00 + return 1; + case FORMAT_VERSION_2_MAGIC_NUMBER: + // Format 2 header is as follows: + // Magic number (4 bytes) 0x9B 0xC1 0x3A 0xFE + // Version number (2 bytes) 0x00 0x02 + // Options (2 bytes) must be 0x00 0x00 + // Header size (4 bytes) : integer, big endian + return (dict[4] << 8) + dict[5]; + default: + return UNKNOWN_FORMAT; + } +} + +inline unsigned int BinaryFormat::getHeaderSize(const uint8_t* const dict) { + switch (detectFormat(dict)) { + case 1: + return FORMAT_VERSION_1_HEADER_SIZE; + case 2: + // See the format of the header in the comment in detectFormat() above + return (dict[8] << 24) + (dict[9] << 16) + (dict[10] << 8) + dict[11]; + default: + return std::numeric_limits<unsigned int>::max(); + } } inline int BinaryFormat::getGroupCountAndForwardPointer(const uint8_t* const dict, int* pos) { diff --git a/native/src/defines.h b/native/src/defines.h index f402efa8d..afa1e0404 100644 --- a/native/src/defines.h +++ b/native/src/defines.h @@ -162,9 +162,6 @@ static inline void prof_out(void) { #define FLAG_BIGRAM_FREQ 0x7F #define DICTIONARY_VERSION_MIN 200 -// TODO: remove this constant when the switch to the new dict format is over -#define DICTIONARY_HEADER_SIZE 2 -#define NEW_DICTIONARY_HEADER_SIZE 5 #define NOT_VALID_WORD -99 #define NOT_A_CHARACTER -1 #define NOT_A_DISTANCE -1 diff --git a/native/src/dictionary.cpp b/native/src/dictionary.cpp index 822c2151d..8e252f730 100644 --- a/native/src/dictionary.cpp +++ b/native/src/dictionary.cpp @@ -19,6 +19,7 @@ #define LOG_TAG "LatinIME: dictionary.cpp" +#include "binary_format.h" #include "dictionary.h" namespace latinime { @@ -41,10 +42,11 @@ Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, mCorrection = new Correction(typedLetterMultiplier, fullWordMultiplier); mWordsPriorityQueuePool = new WordsPriorityQueuePool( maxWords, SUB_QUEUE_MAX_WORDS, maxWordLength); - mUnigramDictionary = new UnigramDictionary(mDict, typedLetterMultiplier, fullWordMultiplier, - maxWordLength, maxWords, maxAlternatives, IS_LATEST_DICT_VERSION); - mBigramDictionary = new BigramDictionary(mDict, maxWordLength, maxAlternatives, - IS_LATEST_DICT_VERSION, hasBigram(), this); + const unsigned int headerSize = BinaryFormat::getHeaderSize(mDict); + mUnigramDictionary = new UnigramDictionary(mDict + headerSize, typedLetterMultiplier, + fullWordMultiplier, maxWordLength, maxWords, maxAlternatives, IS_LATEST_DICT_VERSION); + mBigramDictionary = new BigramDictionary(mDict + headerSize, maxWordLength, maxAlternatives, + IS_LATEST_DICT_VERSION, true /* hasBigram */, this); } Dictionary::~Dictionary() { @@ -54,10 +56,6 @@ Dictionary::~Dictionary() { delete mBigramDictionary; } -bool Dictionary::hasBigram() { - return ((mDict[1] & 0xFF) == 1); -} - bool Dictionary::isValidWord(unsigned short *word, int length) { return mUnigramDictionary->isValidWord(word, length); } diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp index 155bdcb7a..0b646d1cd 100644 --- a/native/src/unigram_dictionary.cpp +++ b/native/src/unigram_dictionary.cpp @@ -38,8 +38,7 @@ const UnigramDictionary::digraph_t UnigramDictionary::GERMAN_UMLAUT_DIGRAPHS[] = UnigramDictionary::UnigramDictionary(const uint8_t* const streamStart, int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords, int maxProximityChars, const bool isLatestDictVersion) - : DICT_ROOT(streamStart + NEW_DICTIONARY_HEADER_SIZE), - MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords), + : DICT_ROOT(streamStart), MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords), MAX_PROXIMITY_CHARS(maxProximityChars), IS_LATEST_DICT_VERSION(isLatestDictVersion), TYPED_LETTER_MULTIPLIER(typedLetterMultiplier), FULL_WORD_MULTIPLIER(fullWordMultiplier), // TODO : remove this variable. diff --git a/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java b/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java index 937e76c1e..485dba10b 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java +++ b/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java @@ -115,6 +115,7 @@ public class BinaryDictInputOutput { private static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; private static final int MINIMUM_SUPPORTED_VERSION = 1; private static final int MAXIMUM_SUPPORTED_VERSION = 2; + private static final int NOT_A_VERSION_NUMBER = -1; private static final int FIRST_VERSION_WITH_HEADER_SIZE = 2; // No options yet, reserved for future use. @@ -829,24 +830,28 @@ public class BinaryDictInputOutput { buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 16)); buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 8)); buffer[index++] = (byte) (0xFF & VERSION_2_MAGIC_NUMBER); + // Dictionary version. + buffer[index++] = (byte) (0xFF & (version >> 8)); + buffer[index++] = (byte) (0xFF & version); } else { // Magic number for version 1. buffer[index++] = (byte) (0xFF & (VERSION_1_MAGIC_NUMBER >> 8)); buffer[index++] = (byte) (0xFF & VERSION_1_MAGIC_NUMBER); + // Dictionary version. + buffer[index++] = (byte) (0xFF & version); } - // Dictionary version. - buffer[index++] = (byte) (0xFF & version); // Options flags buffer[index++] = (byte) (0xFF & (OPTIONS >> 8)); buffer[index++] = (byte) (0xFF & OPTIONS); if (version >= FIRST_VERSION_WITH_HEADER_SIZE) { final int headerSizeOffset = index; - index += 3; // Size of the header size + index += 4; // Size of the header size // TODO: Write out the header contents here. // Write out the header size. - buffer[headerSizeOffset] = (byte) (0xFF & (index >> 16)); - buffer[headerSizeOffset + 1] = (byte) (0xFF & (index >> 8)); - buffer[headerSizeOffset + 2] = (byte) (0xFF & (index >> 0)); + buffer[headerSizeOffset] = (byte) (0xFF & (index >> 24)); + buffer[headerSizeOffset + 1] = (byte) (0xFF & (index >> 16)); + buffer[headerSizeOffset + 2] = (byte) (0xFF & (index >> 8)); + buffer[headerSizeOffset + 3] = (byte) (0xFF & (index >> 0)); } destination.write(buffer, 0, index); @@ -1122,14 +1127,14 @@ public class BinaryDictInputOutput { } /** - * Helper function to test the magic number of the file. + * Helper function to get the binary format version from the header. */ - private static boolean isExpectedMagicNumber(final RandomAccessFile source) throws IOException { + private static int getFormatVersion(final RandomAccessFile source) throws IOException { final int magic_v1 = source.readUnsignedShort(); - if (VERSION_1_MAGIC_NUMBER == magic_v1) return true; + if (VERSION_1_MAGIC_NUMBER == magic_v1) return source.readUnsignedByte(); final int magic_v2 = (magic_v1 << 16) + source.readUnsignedShort(); - if (VERSION_2_MAGIC_NUMBER == magic_v2) return true; - return false; + if (VERSION_2_MAGIC_NUMBER == magic_v2) return source.readUnsignedShort(); + return NOT_A_VERSION_NUMBER; } /** @@ -1145,15 +1150,9 @@ public class BinaryDictInputOutput { */ public static FusionDictionary readDictionaryBinary(final RandomAccessFile source, final FusionDictionary dict) throws IOException, UnsupportedFormatException { - // Check magic number - if (!isExpectedMagicNumber(source)) { - throw new UnsupportedFormatException("The magic number in this file does not match " - + "the expected value"); - } - // Check file version - final int version = source.readUnsignedByte(); - if (version > MAXIMUM_SUPPORTED_VERSION) { + final int version = getFormatVersion(source); + if (version < MINIMUM_SUPPORTED_VERSION || version > MAXIMUM_SUPPORTED_VERSION ) { throw new UnsupportedFormatException("This file has version " + version + ", but this implementation does not support versions above " + MAXIMUM_SUPPORTED_VERSION); @@ -1166,8 +1165,8 @@ public class BinaryDictInputOutput { if (version < FIRST_VERSION_WITH_HEADER_SIZE) { headerSize = source.getFilePointer(); } else { - headerSize = (source.readUnsignedByte() << 16) + (source.readUnsignedByte() << 8) - + source.readUnsignedByte(); + headerSize = (source.readUnsignedByte() << 24) + (source.readUnsignedByte() << 16) + + (source.readUnsignedByte() << 8) + source.readUnsignedByte(); // read the header body source.seek(headerSize); } @@ -1198,7 +1197,8 @@ public class BinaryDictInputOutput { public static boolean isBinaryDictionary(final String filename) { try { RandomAccessFile f = new RandomAccessFile(filename, "r"); - return isExpectedMagicNumber(f); + final int version = getFormatVersion(f); + return (version >= MINIMUM_SUPPORTED_VERSION && version <= MAXIMUM_SUPPORTED_VERSION); } catch (FileNotFoundException e) { return false; } catch (IOException e) { |