diff options
Diffstat (limited to '')
23 files changed, 350 insertions, 175 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 2dfde9434..37a4bf8f6 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -205,7 +205,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { final boolean subtypeChanged = (oldKeyboard == null) || !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale); final boolean needsToDisplayLanguage = mSubtypeSwitcher.needsToDisplayLanguage( - keyboard.mId.mLocale); + keyboard.mId.mSubtype); keyboardView.startDisplayLanguageOnSpacebar(subtypeChanged, needsToDisplayLanguage, RichInputMethodManager.getInstance().hasMultipleEnabledIMEsOrSubtypes(true)); } diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 3590c486b..8246c924b 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -930,11 +930,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return middleText; } - final String shortText = SubtypeLocaleUtils.getShortDisplayName(subtype); - if (fitsTextIntoWidth(width, shortText, paint)) { - return shortText; - } - return ""; } diff --git a/java/src/com/android/inputmethod/keyboard/internal/NeedsToDisplayLanguage.java b/java/src/com/android/inputmethod/keyboard/internal/NeedsToDisplayLanguage.java new file mode 100644 index 000000000..e548de589 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/internal/NeedsToDisplayLanguage.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import android.view.inputmethod.InputMethodSubtype; + +import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; + +/** + * This class determines that the language name on the spacebar should be displayed or not. + */ +public final class NeedsToDisplayLanguage { + private int mEnabledSubtypeCount; + private boolean mIsSystemLanguageSameAsInputLanguage; + + public boolean needsToDisplayLanguage(final InputMethodSubtype subtype) { + if (SubtypeLocaleUtils.isNoLanguage(subtype)) { + return true; + } + return mEnabledSubtypeCount >= 2 || !mIsSystemLanguageSameAsInputLanguage; + } + + public void updateEnabledSubtypeCount(final int count) { + mEnabledSubtypeCount = count; + } + + public void updateIsSystemLanguageSameAsInputLanguage(final boolean isSame) { + mIsSystemLanguageSameAsInputLanguage = isSame; + } +} diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index c986eb2ef..60ac1ba48 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -28,9 +28,10 @@ import com.android.inputmethod.latin.makedict.FormatSpec; import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions; import com.android.inputmethod.latin.makedict.UnsupportedFormatException; import com.android.inputmethod.latin.makedict.WordProperty; -import com.android.inputmethod.latin.personalization.PersonalizationHelper; import com.android.inputmethod.latin.settings.NativeSuggestOptions; +import com.android.inputmethod.latin.utils.BinaryDictionaryUtils; 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; @@ -81,6 +82,8 @@ public final class BinaryDictionary extends Dictionary { public static final int FORMAT_WORD_PROPERTY_LEVEL_INDEX = 2; public static final int FORMAT_WORD_PROPERTY_COUNT_INDEX = 3; + public static final String DICT_FILE_NAME_SUFFIX_FOR_MIGRATION = ".migrate"; + private long mNativeDict; private final Locale mLocale; private final long mDictSize; @@ -458,6 +461,24 @@ public final class BinaryDictionary extends Dictionary { return needsToRunGCNative(mNativeDict, mindsBlockByGC); } + public boolean migrateTo(final int newFormatVersion) { + if (!isValidDictionary()) { + return false; + } + final String tmpDictFilePath = mDictFilePath + DICT_FILE_NAME_SUFFIX_FOR_MIGRATION; + // TODO: Implement migrateNative(tmpDictFilePath, newFormatVersion). + close(); + final File dictFile = new File(mDictFilePath); + final File tmpDictFile = new File(tmpDictFilePath); + FileUtils.deleteRecursively(dictFile); + if (!BinaryDictionaryUtils.renameDict(tmpDictFile, dictFile)) { + return false; + } + loadDictionary(dictFile.getAbsolutePath(), 0 /* startOffset */, + dictFile.length(), mIsUpdatable); + return true; + } + @UsedForTesting public int calculateProbability(final int unigramProbability, final int bigramProbability) { if (!isValidDictionary()) return NOT_A_PROBABILITY; diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java index c2941e424..4e17f8389 100644 --- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java @@ -262,11 +262,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { } @Override - protected boolean needsToReloadAfterCreation() { - return true; - } - - @Override protected boolean haveContentsChanged() { final long startTime = SystemClock.uptimeMillis(); final int contactCount = getContactCount(); diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index 7847738e0..92b535458 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -137,6 +137,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return formatVersion == FormatSpec.VERSION4; } + private boolean needsToMigrateDictionary(final int formatVersion) { + // TODO: Check version. + return false; + } + public boolean isValidDictionaryLocked() { return mBinaryDictionary.isValidDictionary(); } @@ -269,6 +274,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } private void runGCAfterAllPrioritizedTasksIfRequiredLocked(final boolean mindsBlockByGC) { + if (mBinaryDictionary == null) { + return; + } // needsToRunGC() have to be called with lock. if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) { if (setProcessingLargeTaskIfNot()) { @@ -357,6 +365,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { public void run() { final boolean locked = setProcessingLargeTaskIfNot(); try { + if (mBinaryDictionary == null) { + return; + } mBinaryDictionary.addMultipleDictionaryEntries( languageModelParams.toArray( new LanguageModelParam[languageModelParams.size()])); @@ -471,15 +482,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { if (oldBinaryDictionary != null) { oldBinaryDictionary.close(); } + if (mBinaryDictionary.isValidDictionary() + && needsToMigrateDictionary(mBinaryDictionary.getFormatVersion())) { + mBinaryDictionary.migrateTo(DICTIONARY_FORMAT_VERSION); + } } /** - * Abstract method for checking if it is required to reload the dictionary before writing - * a binary dictionary. - */ - abstract protected boolean needsToReloadAfterCreation(); - - /** * Create a new binary dictionary and load initial contents. */ private void createNewDictionaryLocked() { @@ -496,6 +505,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } private void flushDictionaryLocked() { + if (mBinaryDictionary == null) { + return; + } if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) { mBinaryDictionary.flushWithGC(); } else { diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 935dd9667..d4301229c 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -34,6 +34,7 @@ import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils; import com.android.inputmethod.keyboard.KeyboardSwitcher; +import com.android.inputmethod.keyboard.internal.NeedsToDisplayLanguage; import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; @@ -89,23 +90,6 @@ public final class SubtypeSwitcher { false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */, SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE); - static final class NeedsToDisplayLanguage { - private int mEnabledSubtypeCount; - private boolean mIsSystemLanguageSameAsInputLanguage; - - public boolean getValue() { - return mEnabledSubtypeCount >= 2 || !mIsSystemLanguageSameAsInputLanguage; - } - - public void updateEnabledSubtypeCount(final int count) { - mEnabledSubtypeCount = count; - } - - public void updateIsSystemLanguageSameAsInputLanguage(final boolean isSame) { - mIsSystemLanguageSameAsInputLanguage = isSame; - } - } - public static SubtypeSwitcher getInstance() { return sInstance; } @@ -265,14 +249,8 @@ public final class SubtypeSwitcher { // Subtype Switching functions // ////////////////////////////////// - public boolean needsToDisplayLanguage(final Locale keyboardLocale) { - if (keyboardLocale.toString().equals(SubtypeLocaleUtils.NO_LANGUAGE)) { - return true; - } - if (!keyboardLocale.equals(getCurrentSubtypeLocale())) { - return false; - } - return mNeedsToDisplayLanguage.getValue(); + public boolean needsToDisplayLanguage(final InputMethodSubtype subtype) { + return mNeedsToDisplayLanguage.needsToDisplayLanguage(subtype); } public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() { diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java index 8078ab541..8838e27c4 100644 --- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java @@ -269,9 +269,4 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { protected boolean haveContentsChanged() { return true; } - - @Override - protected boolean needsToReloadAfterCreation() { - return true; - } } diff --git a/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java b/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java index 9dcd63f0c..5fcbb6357 100644 --- a/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java +++ b/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin.makedict; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.BinaryDictionary; import com.android.inputmethod.latin.utils.CombinedFormatUtils; @@ -30,6 +31,7 @@ public final class ProbabilityInfo { public final int mLevel; public final int mCount; + @UsedForTesting public static ProbabilityInfo max(final ProbabilityInfo probabilityInfo1, final ProbabilityInfo probabilityInfo2) { if (probabilityInfo1 == null) { diff --git a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java index d94cec424..853392200 100644 --- a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java +++ b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java @@ -42,6 +42,7 @@ public final class WordProperty implements Comparable<WordProperty> { private int mHashCode = 0; + @UsedForTesting public WordProperty(final String word, final ProbabilityInfo probabilityInfo, final ArrayList<WeightedString> shortcutTargets, final ArrayList<WeightedString> bigrams, diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java index 074ec4074..6f84e1f10 100644 --- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java +++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java @@ -91,11 +91,6 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB return false; } - @Override - protected boolean needsToReloadAfterCreation() { - return false; - } - public void addMultipleDictionaryEntriesToDictionary( final ArrayList<LanguageModelParam> languageModelParams, final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) { diff --git a/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java b/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java index 638830046..b4658b531 100644 --- a/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java @@ -26,6 +26,8 @@ import java.io.File; import java.io.IOException; import java.util.Locale; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public final class BinaryDictionaryUtils { private static final String TAG = BinaryDictionaryUtils.class.getSimpleName(); @@ -64,6 +66,31 @@ public final class BinaryDictionaryUtils { return header; } + public static boolean renameDict(final File dictFile, final File newDictFile) { + if (dictFile.isFile()) { + return dictFile.renameTo(newDictFile); + } else if (dictFile.isDirectory()) { + final String dictName = dictFile.getName(); + final String newDictName = newDictFile.getName(); + if (newDictFile.exists()) { + return false; + } + for (final File file : dictFile.listFiles()) { + if (!file.isFile()) { + continue; + } + final String fileName = file.getName(); + final String newFileName = fileName.replaceFirst( + Pattern.quote(dictName), Matcher.quoteReplacement(newDictName)); + if (!file.renameTo(new File(dictFile, newFileName))) { + return false; + } + } + return dictFile.renameTo(newDictFile); + } + return false; + } + public static boolean createEmptyDictFile(final String filePath, final long dictVersion, final Locale locale, final Map<String, String> attributeMap) { final String[] keyArray = new String[attributeMap.size()]; diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java index acd16a9e4..5ce977d5e 100644 --- a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java +++ b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java @@ -110,6 +110,9 @@ public final class LanguageModelParam { final LanguageModelParam languageModelParam = detectWhetherVaildWordOrNotAndGetLanguageModelParam( prevWord, tempWord, timestamp, dictionaryFacilitator); + if (languageModelParam == null) { + continue; + } languageModelParams.add(languageModelParam); prevWord = languageModelParam.mTargetWord; } @@ -120,6 +123,9 @@ public final class LanguageModelParam { final String prevWord, final String targetWord, final int timestamp, final DictionaryFacilitatorForSuggest dictionaryFacilitator) { final Locale locale = dictionaryFacilitator.getLocale(); + if (locale == null) { + return null; + } if (!dictionaryFacilitator.isValidWord(targetWord, true /* ignoreCase */)) { // OOV word. return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp, diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java index b3871bfb4..4f556f972 100644 --- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java @@ -201,11 +201,11 @@ public final class SubtypeLocaleUtils { // fr_CH swiss F Français (Suisse) // de qwertz F Deutsch // de_CH swiss T Deutsch (Schweiz) - // zz qwerty F No language (QWERTY) in system locale + // zz qwerty F Alphabet (QWERTY) in system locale // fr qwertz T Français (QWERTZ) // de qwerty T Deutsch (QWERTY) // en_US azerty T English (US) (AZERTY) exception - // zz azerty T No language (AZERTY) in system locale + // zz azerty T Alphabet (AZERTY) in system locale private static String getReplacementString(final InputMethodSubtype subtype, final Locale displayLocale) { @@ -294,21 +294,21 @@ public final class SubtypeLocaleUtils { // InputMethodSubtype's display name for spacebar text in its locale. // isAdditionalSubtype (T=true, F=false) - // locale layout | Short Middle Full - // ------ ------- - ---- --------- ---------------------- - // en_US qwerty F En English English (US) exception - // en_GB qwerty F En English English (UK) exception - // es_US spanish F Es Español Español (EE.UU.) exception - // fr azerty F Fr Français Français - // fr_CA qwerty F Fr Français Français (Canada) - // fr_CH swiss F Fr Français Français (Suisse) - // de qwertz F De Deutsch Deutsch - // de_CH swiss T De Deutsch Deutsch (Schweiz) - // zz qwerty F QWERTY QWERTY - // fr qwertz T Fr Français Français - // de qwerty T De Deutsch Deutsch - // en_US azerty T En English English (US) - // zz azerty T AZERTY AZERTY + // locale layout | Middle Full + // ------ ------- - --------- ---------------------- + // en_US qwerty F English English (US) exception + // en_GB qwerty F English English (UK) exception + // es_US spanish F Español Español (EE.UU.) exception + // fr azerty F Français Français + // fr_CA qwerty F Français Français (Canada) + // fr_CH swiss F Français Français (Suisse) + // de qwertz F Deutsch Deutsch + // de_CH swiss T Deutsch Deutsch (Schweiz) + // zz qwerty F QWERTY QWERTY + // fr qwertz T Français Français + // de qwerty T Deutsch Deutsch + // en_US azerty T English English (US) + // zz azerty T AZERTY AZERTY // Get InputMethodSubtype's full display name in its locale. public static String getFullDisplayName(final InputMethodSubtype subtype) { @@ -327,15 +327,6 @@ public final class SubtypeLocaleUtils { return getSubtypeLocaleDisplayName(locale.getLanguage()); } - // Get InputMethodSubtype's short display name in its locale. - public static String getShortDisplayName(final InputMethodSubtype subtype) { - if (isNoLanguage(subtype)) { - return ""; - } - final Locale locale = getSubtypeLocale(subtype); - return StringUtils.capitalizeFirstCodePoint(locale.getLanguage(), locale); - } - // TODO: Get this information from the framework instead of maintaining here by ourselves. // Sorted list of known Right-To-Left language codes. private static final String[] SORTED_RTL_LANGUAGES = { diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h index 3118cdfa3..258aa9ce3 100644 --- a/native/jni/src/suggest/core/dicnode/dic_node.h +++ b/native/jni/src/suggest/core/dicnode/dic_node.h @@ -83,14 +83,6 @@ class DicNode { #if DEBUG_DICT DicNodeProfiler mProfiler; #endif - ////////////////// - // Memory utils // - ////////////////// - AK_FORCE_INLINE static void managedDelete(DicNode *node) { - node->remove(); - } - // end - ///////////////// AK_FORCE_INLINE DicNode() : @@ -158,7 +150,7 @@ class DicNode { PROF_NODE_COPY(&dicNode->mProfiler, mProfiler); } - AK_FORCE_INLINE void remove() { + AK_FORCE_INLINE void finalize() { mIsUsed = false; if (mReleaseListener) { mReleaseListener->onReleased(this); @@ -478,17 +470,7 @@ class DicNode { mReleaseListener = releaseListener; } - AK_FORCE_INLINE bool compare(const DicNode *right) { - if (!isUsed() && !right->isUsed()) { - // Compare pointer values here for stable comparison - return this > right; - } - if (!isUsed()) { - return true; - } - if (!right->isUsed()) { - return false; - } + AK_FORCE_INLINE bool compare(const DicNode *right) const { // Promote exact matches to prevent them from being pruned. const bool leftExactMatch = ErrorTypeUtils::isExactMatch(getContainedErrorTypes()); const bool rightExactMatch = ErrorTypeUtils::isExactMatch(right->getContainedErrorTypes()); diff --git a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h index 1f02731a5..213b1b968 100644 --- a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h +++ b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h @@ -68,15 +68,15 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { } setMaxSize(maxSize); for (int i = 0; i < mCapacity + 1; ++i) { - mDicNodesBuf[i].remove(); + mDicNodesBuf[i].finalize(); mDicNodesBuf[i].setReleaseListener(this); - mUnusedNodeIndices[i] = i == mCapacity ? NOT_A_NODE_ID : static_cast<int>(i) + 1; + mUnusedNodeIndices[i] = (i == mCapacity) ? NOT_A_NODE_ID : (i + 1); } mNextUnusedNodeId = 0; } // Copy - AK_FORCE_INLINE DicNode *copyPush(DicNode *dicNode) { + AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode) { return copyPush(dicNode, mMaxSize); } @@ -89,11 +89,11 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { if (dest) { DicNodeUtils::initByCopy(node, dest); } - node->remove(); + node->finalize(); mDicNodesQueue.pop(); } - void onReleased(DicNode *dicNode) { + void onReleased(const DicNode *dicNode) { const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]); if (mUnusedNodeIndices[index] != NOT_A_NODE_ID) { // it's already released @@ -118,7 +118,8 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePriorityQueue); static const int NOT_A_NODE_ID = -1; - AK_FORCE_INLINE static bool compareDicNode(DicNode *left, DicNode *right) { + AK_FORCE_INLINE static bool compareDicNode(const DicNode *const left, + const DicNode *const right) { return left->compare(right); } @@ -141,10 +142,10 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { } AK_FORCE_INLINE void pop() { - copyPop(0); + copyPop(nullptr); } - AK_FORCE_INLINE bool betterThanWorstDicNode(DicNode *dicNode) const { + AK_FORCE_INLINE bool betterThanWorstDicNode(const DicNode *const dicNode) const { DicNode *worstNode = mDicNodesQueue.top(); if (!worstNode) { return true; @@ -154,7 +155,7 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { AK_FORCE_INLINE DicNode *searchEmptyDicNode() { if (mCapacity == 0) { - return 0; + return nullptr; } if (mNextUnusedNodeId == NOT_A_NODE_ID) { AKLOGI("No unused node found."); @@ -163,7 +164,7 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { i, mDicNodesBuf[i].isUsed(), mUnusedNodeIndices[i]); } ASSERT(false); - return 0; + return nullptr; } DicNode *dicNode = &mDicNodesBuf[mNextUnusedNodeId]; markNodeAsUsed(dicNode); @@ -179,7 +180,7 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { AK_FORCE_INLINE DicNode *pushPoolNodeWithMaxSize(DicNode *dicNode, const int maxSize) { if (!dicNode) { - return 0; + return nullptr; } if (!isFull(maxSize)) { mDicNodesQueue.push(dicNode); @@ -190,16 +191,16 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { mDicNodesQueue.push(dicNode); return dicNode; } - dicNode->remove(); - return 0; + dicNode->finalize(); + return nullptr; } // Copy - AK_FORCE_INLINE DicNode *copyPush(DicNode *dicNode, const int maxSize) { + AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode, const int maxSize) { return pushPoolNodeWithMaxSize(newDicNode(dicNode), maxSize); } - AK_FORCE_INLINE DicNode *newDicNode(DicNode *dicNode) { + AK_FORCE_INLINE DicNode *newDicNode(const DicNode *const dicNode) { DicNode *newNode = searchEmptyDicNode(); if (newNode) { DicNodeUtils::initByCopy(dicNode, newNode); diff --git a/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h b/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h index 2ca4f21bd..c3f432951 100644 --- a/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h +++ b/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h @@ -27,7 +27,7 @@ class DicNodeReleaseListener { public: DicNodeReleaseListener() {} virtual ~DicNodeReleaseListener() {} - virtual void onReleased(DicNode *dicNode) = 0; + virtual void onReleased(const DicNode *dicNode) = 0; private: DISALLOW_COPY_AND_ASSIGN(DicNodeReleaseListener); }; diff --git a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h index d4769e739..6b8dc8c96 100644 --- a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h +++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h @@ -100,14 +100,7 @@ class DicNodesCache { } AK_FORCE_INLINE void copyPushNextActive(DicNode *dicNode) { - DicNode *pushedDicNode = mNextActiveDicNodes->copyPush(dicNode); - if (!pushedDicNode) { - if (dicNode->isCached()) { - dicNode->remove(); - } - // We simply drop any dic node that was not cached, ignoring the slim chance - // that one of its children represents what the user really wanted. - } + mNextActiveDicNodes->copyPush(dicNode); } void popTerminal(DicNode *dest) { diff --git a/native/jni/src/suggest/core/result/suggestions_output_utils.cpp b/native/jni/src/suggest/core/result/suggestions_output_utils.cpp index b40f3226f..d07f5ca41 100644 --- a/native/jni/src/suggest/core/result/suggestions_output_utils.cpp +++ b/native/jni/src/suggest/core/result/suggestions_output_utils.cpp @@ -131,7 +131,6 @@ const int SuggestionsOutputUtils::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16; true /* forceCommit */, boostExactMatches) : finalScore; outputShortcuts(&shortcutIt, shortcutBaseScore, sameAsTyped, outSuggestionResults); } - DicNode::managedDelete(terminalDicNode); } scoringPolicy->getMostProbableString(traverseSession, languageWeight, outSuggestionResults); } diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp index 2ea6452af..303182cf4 100644 --- a/native/jni/src/suggest/core/suggest.cpp +++ b/native/jni/src/suggest/core/suggest.cpp @@ -265,7 +265,6 @@ void Suggest::processExpandedDicNode( traverseSession->getDicTraverseCache()->copyPushNextActive(dicNode); } } - DicNode::managedDelete(dicNode); } void Suggest::processDicNodeAsMatch(DicTraverseSession *traverseSession, @@ -388,7 +387,6 @@ void Suggest::processDicNodeAsTransposition(DicTraverseSession *traverseSession, processExpandedDicNode(traverseSession, childDicNode2); } } - DicNode::managedDelete(childDicNodes1[i]); } } diff --git a/tests/src/com/android/inputmethod/keyboard/internal/NeedsToDisplayLanguageTests.java b/tests/src/com/android/inputmethod/keyboard/internal/NeedsToDisplayLanguageTests.java new file mode 100644 index 000000000..e03bce1e0 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/internal/NeedsToDisplayLanguageTests.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import android.content.Context; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.inputmethod.InputMethodSubtype; + +import com.android.inputmethod.latin.RichInputMethodManager; +import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; + +import java.util.Locale; + +@SmallTest +public class NeedsToDisplayLanguageTests extends AndroidTestCase { + private final NeedsToDisplayLanguage mNeedsToDisplayLanguage = new NeedsToDisplayLanguage(); + + private RichInputMethodManager mRichImm; + + InputMethodSubtype EN_US; + InputMethodSubtype FR; + InputMethodSubtype ZZ; + + @Override + protected void setUp() throws Exception { + super.setUp(); + final Context context = getContext(); + RichInputMethodManager.init(context); + mRichImm = RichInputMethodManager.getInstance(); + SubtypeLocaleUtils.init(context); + + EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.US.toString(), "qwerty"); + FR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.FRENCH.toString(), "azerty"); + ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + SubtypeLocaleUtils.NO_LANGUAGE, "qwerty"); + } + + public void testOneSubtype() { + mNeedsToDisplayLanguage.updateEnabledSubtypeCount(1); + + mNeedsToDisplayLanguage.updateIsSystemLanguageSameAsInputLanguage(true /* isSame */); + assertFalse("one same English (US)", mNeedsToDisplayLanguage.needsToDisplayLanguage(EN_US)); + assertTrue("one same NoLanguage", mNeedsToDisplayLanguage.needsToDisplayLanguage(ZZ)); + + mNeedsToDisplayLanguage.updateIsSystemLanguageSameAsInputLanguage(false /* isSame */); + assertTrue("one diff English (US)", mNeedsToDisplayLanguage.needsToDisplayLanguage(EN_US)); + assertTrue("one diff NoLanguage", mNeedsToDisplayLanguage.needsToDisplayLanguage(ZZ)); + } + + public void testTwoSubtype() { + mNeedsToDisplayLanguage.updateEnabledSubtypeCount(2); + + mNeedsToDisplayLanguage.updateIsSystemLanguageSameAsInputLanguage(true /* isSame */); + assertTrue("two same English (US)", mNeedsToDisplayLanguage.needsToDisplayLanguage(EN_US)); + assertTrue("two same French", mNeedsToDisplayLanguage.needsToDisplayLanguage(FR)); + assertTrue("two same NoLanguage", mNeedsToDisplayLanguage.needsToDisplayLanguage(ZZ)); + + mNeedsToDisplayLanguage.updateIsSystemLanguageSameAsInputLanguage(false /* isSame */); + assertTrue("two diff English (US)", mNeedsToDisplayLanguage.needsToDisplayLanguage(EN_US)); + assertTrue("two diff French", mNeedsToDisplayLanguage.needsToDisplayLanguage(ZZ)); + assertTrue("two diff NoLanguage", mNeedsToDisplayLanguage.needsToDisplayLanguage(FR)); + } +} diff --git a/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java new file mode 100644 index 000000000..d86639101 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin.utils; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; + +import com.android.inputmethod.latin.BinaryDictionary; +import com.android.inputmethod.latin.makedict.DictionaryHeader; +import com.android.inputmethod.latin.makedict.FormatSpec; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@LargeTest +public class BinaryDictionaryUtilsTests extends AndroidTestCase { + private static final String TEST_DICT_FILE_EXTENSION = ".testDict"; + private static final String TEST_LOCALE = "test"; + + private File createEmptyDictionaryAndGetFile(final String dictId, + final int formatVersion) throws IOException { + if (formatVersion == FormatSpec.VERSION4) { + return createEmptyVer4DictionaryAndGetFile(dictId); + } else { + throw new IOException("Dictionary format version " + formatVersion + + " is not supported."); + } + } + + private File createEmptyVer4DictionaryAndGetFile(final String dictId) throws IOException { + final File file = getDictFile(dictId); + FileUtils.deleteRecursively(file); + Map<String, String> attributeMap = new HashMap<String, String>(); + attributeMap.put(DictionaryHeader.DICTIONARY_ID_KEY, dictId); + attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY, + String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()))); + attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY, + DictionaryHeader.ATTRIBUTE_VALUE_TRUE); + attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY, + DictionaryHeader.ATTRIBUTE_VALUE_TRUE); + if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), FormatSpec.VERSION4, + LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) { + return file; + } else { + throw new IOException("Empty dictionary " + file.getAbsolutePath() + + " cannot be created."); + } + } + + private File getDictFile(final String dictId) { + return new File(getContext().getCacheDir(), dictId + TEST_DICT_FILE_EXTENSION); + } + + public void testRenameDictionary() { + final int formatVersion = FormatSpec.VERSION4; + File dictFile0 = null; + try { + dictFile0 = createEmptyDictionaryAndGetFile("MoveFromDictionary", formatVersion); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + final File dictFile1 = getDictFile("MoveToDictionary"); + FileUtils.deleteRecursively(dictFile1); + assertTrue(BinaryDictionaryUtils.renameDict(dictFile0, dictFile1)); + assertFalse(dictFile0.exists()); + assertTrue(dictFile1.exists()); + BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile1.getAbsolutePath(), + 0 /* offset */, dictFile1.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + assertTrue(binaryDictionary.isValidDictionary()); + assertTrue(binaryDictionary.getFormatVersion() == formatVersion); + binaryDictionary.close(); + } +} diff --git a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java index 25f57eba6..eb8a61a16 100644 --- a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java @@ -213,13 +213,13 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { // fr_CH swiss F Français (Suisse) // de qwertz F Allemand // de_CH swiss F Allemand (Suisse) - // zz qwerty F Aucune langue (QWERTY) + // zz qwerty F Alphabet latin (QWERTY) // fr qwertz T Français (QWERTZ) // de qwerty T Allemand (QWERTY) // en_US azerty T Anglais (États-Unis) (AZERTY) exception // en_UK dvorak T Anglais (Royaume-Uni) (Dvorak) exception // es_US colemak T Espagnol (États-Unis) (Colemak) exception - // zz pc T Alphabet (PC) + // zz pc T Alphabet latin (PC) public void testPredefinedSubtypesInFrenchSystemLocale() { final RunInLocale<Void> tests = new RunInLocale<Void>() { @@ -303,39 +303,23 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { } } - public void testAllShortDisplayNameForSpacebar() { - for (final InputMethodSubtype subtype : mSubtypesList) { - final String subtypeName = SubtypeLocaleUtils - .getSubtypeDisplayNameInSystemLocale(subtype); - final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype); - final String spacebarText = SubtypeLocaleUtils.getShortDisplayName(subtype); - final String languageCode = StringUtils.capitalizeFirstCodePoint( - locale.getLanguage(), locale); - if (SubtypeLocaleUtils.isNoLanguage(subtype)) { - assertEquals(subtypeName, "", spacebarText); - } else { - assertEquals(subtypeName, languageCode, spacebarText); - } - } - } - // InputMethodSubtype's display name for spacebar text in its locale. // isAdditionalSubtype (T=true, F=false) - // locale layout | Short Middle Full - // ------ ------- - ---- --------- ---------------------- - // en_US qwerty F En English English (US) exception - // en_GB qwerty F En English English (UK) exception - // es_US spanish F Es Español Español (EE.UU.) exception - // fr azerty F Fr Français Français - // fr_CA qwerty F Fr Français Français (Canada) - // fr_CH swiss F Fr Français Français (Suisse) - // de qwertz F De Deutsch Deutsch - // de_CH swiss F De Deutsch Deutsch (Schweiz) - // zz qwerty F QWERTY QWERTY - // fr qwertz T Fr Français Français - // de qwerty T De Deutsch Deutsch - // en_US azerty T En English English (US) - // zz azerty T AZERTY AZERTY + // locale layout | Middle Full + // ------ ------- - --------- ---------------------- + // en_US qwerty F English English (US) exception + // en_GB qwerty F English English (UK) exception + // es_US spanish F Español Español (EE.UU.) exception + // fr azerty F Français Français + // fr_CA qwerty F Français Français (Canada) + // fr_CH swiss F Français Français (Suisse) + // de qwertz F Deutsch Deutsch + // de_CH swiss F Deutsch Deutsch (Schweiz) + // zz qwerty F QWERTY QWERTY + // fr qwertz T Français Français + // de qwerty T Deutsch Deutsch + // en_US azerty T English English (US) + // zz azerty T AZERTY AZERTY private final RunInLocale<Void> testsPredefinedSubtypesForSpacebar = new RunInLocale<Void>() { @Override @@ -363,16 +347,6 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { assertEquals("de ", "Deutsch", SubtypeLocaleUtils.getMiddleDisplayName(DE)); assertEquals("de_CH", "Deutsch", SubtypeLocaleUtils.getMiddleDisplayName(DE_CH)); assertEquals("zz ", "QWERTY", SubtypeLocaleUtils.getMiddleDisplayName(ZZ)); - - assertEquals("en_US", "En", SubtypeLocaleUtils.getShortDisplayName(EN_US)); - assertEquals("en_GB", "En", SubtypeLocaleUtils.getShortDisplayName(EN_GB)); - assertEquals("es_US", "Es", SubtypeLocaleUtils.getShortDisplayName(ES_US)); - assertEquals("fr ", "Fr", SubtypeLocaleUtils.getShortDisplayName(FR)); - assertEquals("fr_CA", "Fr", SubtypeLocaleUtils.getShortDisplayName(FR_CA)); - assertEquals("fr_CH", "Fr", SubtypeLocaleUtils.getShortDisplayName(FR_CH)); - assertEquals("de ", "De", SubtypeLocaleUtils.getShortDisplayName(DE)); - assertEquals("de_CH", "De", SubtypeLocaleUtils.getShortDisplayName(DE_CH)); - assertEquals("zz ", "", SubtypeLocaleUtils.getShortDisplayName(ZZ)); return null; } }; @@ -397,12 +371,6 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { SubtypeLocaleUtils.getMiddleDisplayName(EN_US_AZERTY)); assertEquals("zz azerty", "AZERTY", SubtypeLocaleUtils.getMiddleDisplayName(ZZ_AZERTY)); - - assertEquals("fr qwertz", "Fr", SubtypeLocaleUtils.getShortDisplayName(FR_QWERTZ)); - assertEquals("de qwerty", "De", SubtypeLocaleUtils.getShortDisplayName(DE_QWERTY)); - assertEquals("en_US azerty", "En", - SubtypeLocaleUtils.getShortDisplayName(EN_US_AZERTY)); - assertEquals("zz azerty", "", SubtypeLocaleUtils.getShortDisplayName(ZZ_AZERTY)); return null; } }; |