aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/inputmethod/event/InputTransaction.java25
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java7
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java18
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java47
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java6
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java11
-rw-r--r--java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java61
-rw-r--r--java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java35
-rw-r--r--native/jni/Android.mk3
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node.cpp5
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node.h69
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_pool.h87
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h142
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_release_listener.h35
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_nodes_cache.h15
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java251
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java171
17 files changed, 551 insertions, 437 deletions
diff --git a/java/src/com/android/inputmethod/event/InputTransaction.java b/java/src/com/android/inputmethod/event/InputTransaction.java
index 2e9014f20..4fe9b403e 100644
--- a/java/src/com/android/inputmethod/event/InputTransaction.java
+++ b/java/src/com/android/inputmethod/event/InputTransaction.java
@@ -40,6 +40,7 @@ public class InputTransaction {
// Outputs
private int mRequiredShiftUpdate = SHIFT_NO_UPDATE;
+ private boolean mRequiresUpdateSuggestions = false;
public InputTransaction(final SettingsValues settingsValues, final Event event,
final long timestamp, final int spaceState, final int shiftState) {
@@ -50,10 +51,34 @@ public class InputTransaction {
mShiftState = shiftState;
}
+ /**
+ * Indicate that this transaction requires some type of shift update.
+ * @param updateType What type of shift update this requires.
+ */
public void requireShiftUpdate(final int updateType) {
mRequiredShiftUpdate = Math.max(mRequiredShiftUpdate, updateType);
}
+
+ /**
+ * Gets what type of shift update this transaction requires.
+ * @return The shift update type.
+ */
public int getRequiredShiftUpdate() {
return mRequiredShiftUpdate;
}
+
+ /**
+ * Indicate that this transaction requires updating the suggestions.
+ */
+ public void setRequiresUpdateSuggestions() {
+ mRequiresUpdateSuggestions = true;
+ }
+
+ /**
+ * Find out whether this transaction requires updating the suggestions.
+ * @return Whether this transaction requires updating the suggestions.
+ */
+ public boolean requiresUpdateSuggestions() {
+ return mRequiresUpdateSuggestions;
+ }
}
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 8246c924b..03425ef1f 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -60,7 +60,7 @@ import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.latin.settings.DebugSettings;
import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.CoordinateUtils;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+import com.android.inputmethod.latin.utils.SpacebarLanguageUtils;
import com.android.inputmethod.latin.utils.TypefaceUtils;
import com.android.inputmethod.latin.utils.UsabilityStudyLogUtils;
import com.android.inputmethod.research.ResearchLogger;
@@ -918,14 +918,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
// Layout language name on spacebar.
private String layoutLanguageOnSpacebar(final Paint paint,
final InputMethodSubtype subtype, final int width) {
-
// Choose appropriate language name to fit into the width.
- final String fullText = SubtypeLocaleUtils.getFullDisplayName(subtype);
+ final String fullText = SpacebarLanguageUtils.getFullDisplayName(subtype);
if (fitsTextIntoWidth(width, fullText, paint)) {
return fullText;
}
- final String middleText = SubtypeLocaleUtils.getMiddleDisplayName(subtype);
+ final String middleText = SpacebarLanguageUtils.getMiddleDisplayName(subtype);
if (fitsTextIntoWidth(width, middleText, paint)) {
return middleText;
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 0c0be82df..53e6232b6 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -38,7 +38,6 @@ import android.net.ConnectivityManager;
import android.os.Debug;
import android.os.IBinder;
import android.os.Message;
-import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.text.TextUtils;
@@ -1230,7 +1229,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final InputTransaction completeInputTransaction =
mInputLogic.onCodeInput(mSettings.getCurrent(), event,
mKeyboardSwitcher.getKeyboardShiftMode(), mHandler);
- updateShiftModeAfterInputTransaction(completeInputTransaction.getRequiredShiftUpdate());
+ updateStateAfterInputTransaction(completeInputTransaction);
mKeyboardSwitcher.onCodeInput(codePoint);
}
@@ -1450,7 +1449,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final InputTransaction completeInputTransaction = mInputLogic.onPickSuggestionManually(
mSettings.getCurrent(), index, suggestionInfo,
mKeyboardSwitcher.getKeyboardShiftMode(), mHandler);
- updateShiftModeAfterInputTransaction(completeInputTransaction.getRequiredShiftUpdate());
+ updateStateAfterInputTransaction(completeInputTransaction);
}
@Override
@@ -1488,8 +1487,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
- private void updateShiftModeAfterInputTransaction(final int requiredShiftUpdate) {
- switch (requiredShiftUpdate) {
+ /**
+ * After an input transaction has been executed, some state must be updated. This includes
+ * the shift state of the keyboard and suggestions. This method looks at the finished
+ * inputTransaction to find out what is necessary and updates the state accordingly.
+ * @param inputTransaction The transaction that has been executed.
+ */
+ private void updateStateAfterInputTransaction(final InputTransaction inputTransaction) {
+ switch (inputTransaction.getRequiredShiftUpdate()) {
case InputTransaction.SHIFT_UPDATE_LATER:
mHandler.postUpdateShiftState();
break;
@@ -1498,6 +1503,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
break;
default: // SHIFT_NO_UPDATE
}
+ if (inputTransaction.requiresUpdateSuggestions()) {
+ mHandler.postUpdateSuggestionStrip();
+ }
}
private void hapticAndAudioFeedback(final int code, final int repeatCount) {
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index e2cdbb39c..ec6bd289a 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -130,8 +130,11 @@ public final class InputLogic {
// so we try using some heuristics to find out about these and fix them.
mConnection.tryFixLyingCursorPosition();
cancelDoubleSpacePeriodCountdown();
- mInputLogicHandler.destroy();
- mInputLogicHandler = new InputLogicHandler(mLatinIME, this);
+ if (InputLogicHandler.NULL_HANDLER == mInputLogicHandler) {
+ mInputLogicHandler = new InputLogicHandler(mLatinIME, this);
+ } else {
+ mInputLogicHandler.reset();
+ }
}
/**
@@ -142,8 +145,7 @@ public final class InputLogic {
mConnection.finishComposingText();
}
resetComposingState(true /* alsoResetLastComposedWord */);
- mInputLogicHandler.destroy();
- mInputLogicHandler = InputLogicHandler.NULL_HANDLER;
+ mInputLogicHandler.reset();
}
/**
@@ -403,7 +405,7 @@ public final class InputLogic {
// A special key, like delete, shift, emoji, or the settings key.
switch (event.mKeyCode) {
case Constants.CODE_DELETE:
- handleBackspace(inputTransaction, handler);
+ handleBackspace(inputTransaction);
LatinImeLogger.logOnDelete(event.mX, event.mY);
break;
case Constants.CODE_SHIFT:
@@ -672,7 +674,7 @@ public final class InputLogic {
commitTyped(inputTransaction.mSettingsValues, LastComposedWord.NOT_A_SEPARATOR);
}
}
- handleNonSeparator(inputTransaction.mSettingsValues, inputTransaction, handler);
+ handleNonSeparator(inputTransaction.mSettingsValues, inputTransaction);
}
return didAutoCorrect;
}
@@ -683,9 +685,7 @@ public final class InputLogic {
* @param inputTransaction The transaction in progress.
*/
private void handleNonSeparator(final SettingsValues settingsValues,
- final InputTransaction inputTransaction,
- // TODO: Remove this argument
- final LatinIME.UIHandler handler) {
+ final InputTransaction inputTransaction) {
final int codePoint = inputTransaction.mEvent.mCodePoint;
// TODO: refactor this method to stop flipping isComposingWord around all the time, and
// make it shorter (possibly cut into several pieces). Also factor handleNonSpecialCharacter
@@ -761,7 +761,7 @@ public final class InputLogic {
// In case the "add to dictionary" hint was still displayed.
mSuggestionStripViewAccessor.dismissAddToDictionaryHint();
}
- handler.postUpdateSuggestionStrip();
+ inputTransaction.setRequiresUpdateSuggestions();
if (settingsValues.mIsInternal) {
LatinImeLoggerUtils.onNonSeparator((char)codePoint, inputTransaction.mEvent.mX,
inputTransaction.mEvent.mY);
@@ -843,7 +843,7 @@ public final class InputLogic {
}
startDoubleSpacePeriodCountdown(inputTransaction);
- handler.postUpdateSuggestionStrip();
+ inputTransaction.setRequiresUpdateSuggestions();
} else {
if (swapWeakSpace) {
swapSwapperAndSpace(inputTransaction);
@@ -879,9 +879,7 @@ public final class InputLogic {
* Handle a press on the backspace key.
* @param inputTransaction The transaction in progress.
*/
- private void handleBackspace(final InputTransaction inputTransaction,
- // TODO: remove this argument
- final LatinIME.UIHandler handler) {
+ private void handleBackspace(final InputTransaction inputTransaction) {
mSpaceState = SpaceState.NONE;
mDeleteCount++;
@@ -910,7 +908,7 @@ public final class InputLogic {
mWordComposer.deleteLast(inputTransaction.mEvent);
}
mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
- handler.postUpdateSuggestionStrip();
+ inputTransaction.setRequiresUpdateSuggestions();
if (!mWordComposer.isComposingWord()) {
// If we just removed the last character, auto-caps mode may have changed so we
// need to re-evaluate.
@@ -921,7 +919,7 @@ public final class InputLogic {
if (inputTransaction.mSettingsValues.mIsInternal) {
LatinImeLoggerUtils.onAutoCorrectionCancellation();
}
- revertCommit(inputTransaction.mSettingsValues, handler);
+ revertCommit(inputTransaction);
return;
}
if (mEnteredText != null && mConnection.sameAsTextBeforeCursor(mEnteredText)) {
@@ -1400,11 +1398,9 @@ public final class InputLogic {
*
* This is triggered upon pressing backspace just after a commit with auto-correction.
*
- * @param settingsValues the current settings values.
+ * @param inputTransaction The transaction in progress.
*/
- private void revertCommit(final SettingsValues settingsValues,
- // TODO: remove this argument
- final LatinIME.UIHandler handler) {
+ private void revertCommit(final InputTransaction inputTransaction) {
final String previousWord = mLastComposedWord.mPrevWord;
final CharSequence originallyTypedWord = mLastComposedWord.mTypedWord;
final CharSequence committedWord = mLastComposedWord.mCommittedWord;
@@ -1448,7 +1444,8 @@ public final class InputLogic {
// Given this, we add it to the list of suggestions, otherwise we discard it.
if (span instanceof SuggestionSpan) {
final SuggestionSpan suggestionSpan = (SuggestionSpan)span;
- if (!suggestionSpan.getLocale().equals(settingsValues.mLocale.toString())) {
+ if (!suggestionSpan.getLocale().equals(
+ inputTransaction.mSettingsValues.mLocale.toString())) {
continue;
}
for (final String suggestion : suggestionSpan.getSuggestions()) {
@@ -1463,11 +1460,11 @@ public final class InputLogic {
}
}
// Add the suggestion list to the list of suggestions.
- textToCommit.setSpan(new SuggestionSpan(settingsValues.mLocale,
+ textToCommit.setSpan(new SuggestionSpan(inputTransaction.mSettingsValues.mLocale,
suggestions.toArray(new String[suggestions.size()]), 0 /* flags */),
0 /* start */, lastCharIndex /* end */, 0 /* flags */);
}
- if (settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) {
+ if (inputTransaction.mSettingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) {
// For languages with spaces, we revert to the typed string, but the cursor is still
// after the separator so we don't resume suggestions. If the user wants to correct
// the word, they have to press backspace again.
@@ -1480,7 +1477,7 @@ public final class InputLogic {
mLatinIME.getCoordinatesForCurrentKeyboard(codePoints), previousWord);
mConnection.setComposingText(textToCommit, 1);
}
- if (settingsValues.mIsInternal) {
+ if (inputTransaction.mSettingsValues.mIsInternal) {
LatinImeLoggerUtils.onSeparator(mLastComposedWord.mSeparatorString,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
}
@@ -1493,7 +1490,7 @@ public final class InputLogic {
// separator.
mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
// We have a separator between the word and the cursor: we should show predictions.
- handler.postUpdateSuggestionStrip();
+ inputTransaction.setRequiresUpdateSuggestions();
}
/**
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
index db96de305..42f0d7c00 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
@@ -43,7 +43,7 @@ class InputLogicHandler implements Handler.Callback {
// is initialized, though probably only the monkey can actually do this.
public static final InputLogicHandler NULL_HANDLER = new InputLogicHandler() {
@Override
- public void destroy() {}
+ public void reset() {}
@Override
public boolean handleMessage(final Message msg) { return true; }
@Override
@@ -75,8 +75,8 @@ class InputLogicHandler implements Handler.Callback {
mInputLogic = inputLogic;
}
- public void destroy() {
- mNonUIThreadHandler.getLooper().quit();
+ public void reset() {
+ mNonUIThreadHandler.removeCallbacksAndMessages(null);
}
/**
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index a07e8eb6a..6a52481b9 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -268,6 +268,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
// if it doesn't. See documentation for binarySearch.
final int insertIndex = positionIndex >= 0 ? positionIndex : -positionIndex - 1;
+ // Weak <- insertIndex == 0, ..., insertIndex == mLength -> Strong
if (insertIndex == 0 && mLength >= mMaxLength) {
// In the future, we may want to keep track of the best suggestion score even if
// we are asked for 0 suggestions. In this case, we can use the following
@@ -285,11 +286,6 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
// }
return true;
}
- if (insertIndex >= mMaxLength) {
- // We found a suggestion, but its score is too weak to be kept considering
- // the suggestion limit.
- return true;
- }
final String wordString = new String(word, wordOffset, wordLength);
if (mLength < mMaxLength) {
@@ -297,12 +293,13 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
++mLength;
System.arraycopy(mScores, insertIndex, mScores, insertIndex + 1, copyLen);
mSuggestions.add(insertIndex, wordString);
+ mScores[insertIndex] = score;
} else {
- System.arraycopy(mScores, 1, mScores, 0, insertIndex);
+ System.arraycopy(mScores, 1, mScores, 0, insertIndex - 1);
mSuggestions.add(insertIndex, wordString);
mSuggestions.remove(0);
+ mScores[insertIndex - 1] = score;
}
- mScores[insertIndex] = score;
return true;
}
diff --git a/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java b/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java
new file mode 100644
index 000000000..89837c641
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java
@@ -0,0 +1,61 @@
+/*
+ * 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.view.inputmethod.InputMethodSubtype;
+
+import java.util.Locale;
+
+public final class SpacebarLanguageUtils {
+ private SpacebarLanguageUtils() {
+ // Intentional empty constructor for utility class.
+ }
+
+ // InputMethodSubtype's display name for spacebar text in its locale.
+ // isAdditionalSubtype (T=true, F=false)
+ // 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) {
+ if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+ return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype);
+ }
+ return SubtypeLocaleUtils.getSubtypeLocaleDisplayName(subtype.getLocale());
+ }
+
+ // Get InputMethodSubtype's middle display name in its locale.
+ public static String getMiddleDisplayName(final InputMethodSubtype subtype) {
+ if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+ return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype);
+ }
+ final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
+ return SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage());
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
index 4f556f972..2452864d5 100644
--- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
@@ -292,41 +292,6 @@ public final class SubtypeLocaleUtils {
return keyboardLayoutSet;
}
- // InputMethodSubtype's display name for spacebar text in its locale.
- // isAdditionalSubtype (T=true, F=false)
- // 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) {
- if (isNoLanguage(subtype)) {
- return getKeyboardLayoutSetDisplayName(subtype);
- }
- return getSubtypeLocaleDisplayName(subtype.getLocale());
- }
-
- // Get InputMethodSubtype's middle display name in its locale.
- public static String getMiddleDisplayName(final InputMethodSubtype subtype) {
- if (isNoLanguage(subtype)) {
- return getKeyboardLayoutSetDisplayName(subtype);
- }
- final Locale locale = getSubtypeLocale(subtype);
- return getSubtypeLocaleDisplayName(locale.getLanguage());
- }
-
// 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/Android.mk b/native/jni/Android.mk
index afb32d1da..c1372bd70 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -34,9 +34,6 @@ LOCAL_CFLAGS += -Werror -Wall -Wextra -Weffc++ -Wformat=2 -Wcast-qual -Wcast-ali
# To suppress compiler warnings for unused variables/functions used for debug features etc.
LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-function
-# For C++11
-LOCAL_CFLAGS += -std=c++11
-
include $(LOCAL_PATH)/NativeFileList.mk
LOCAL_SRC_FILES := \
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.cpp b/native/jni/src/suggest/core/dicnode/dic_node.cpp
index 73855977e..414dc3b1e 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node.cpp
@@ -24,8 +24,7 @@ DicNode::DicNode(const DicNode &dicNode)
mProfiler(dicNode.mProfiler),
#endif
mDicNodeProperties(dicNode.mDicNodeProperties), mDicNodeState(dicNode.mDicNodeState),
- mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion), mIsUsed(dicNode.mIsUsed),
- mReleaseListener(nullptr) {
+ mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion) {
/* empty */
}
@@ -36,8 +35,6 @@ DicNode &DicNode::operator=(const DicNode &dicNode) {
mDicNodeProperties = dicNode.mDicNodeProperties;
mDicNodeState = dicNode.mDicNodeState;
mIsCachedForNextSuggestion = dicNode.mIsCachedForNextSuggestion;
- mIsUsed = dicNode.mIsUsed;
- mReleaseListener = dicNode.mReleaseListener;
return *this;
}
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index 258aa9ce3..47f5ec0d7 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -19,7 +19,6 @@
#include "defines.h"
#include "suggest/core/dicnode/dic_node_profiler.h"
-#include "suggest/core/dicnode/dic_node_release_listener.h"
#include "suggest/core/dicnode/dic_node_utils.h"
#include "suggest/core/dicnode/internal/dic_node_state.h"
#include "suggest/core/dicnode/internal/dic_node_properties.h"
@@ -45,7 +44,8 @@
+ mDicNodeState.mDicNodeStateOutput.getPrevWordsLength(), \
charBuf, NELEMS(charBuf)); \
AKLOGI("#%8s, %5f, %5f, %5f, %5f, %s, %d, %5f,", header, \
- getSpatialDistanceForScoring(), getLanguageDistanceForScoring(), \
+ getSpatialDistanceForScoring(), \
+ mDicNodeState.mDicNodeStateScoring.getLanguageDistance(), \
getNormalizedCompoundDistance(), getRawLength(), charBuf, \
getInputIndex(0), getNormalizedCompoundDistanceAfterFirstWord()); \
} while (0)
@@ -89,8 +89,7 @@ class DicNode {
#if DEBUG_DICT
mProfiler(),
#endif
- mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false),
- mIsUsed(false), mReleaseListener(nullptr) {}
+ mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false) {}
DicNode(const DicNode &dicNode);
DicNode &operator=(const DicNode &dicNode);
@@ -98,7 +97,6 @@ class DicNode {
// Init for copy
void initByCopy(const DicNode *const dicNode) {
- mIsUsed = true;
mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
mDicNodeProperties.initByCopy(&dicNode->mDicNodeProperties);
mDicNodeState.initByCopy(&dicNode->mDicNodeState);
@@ -107,7 +105,6 @@ class DicNode {
// Init for root with prevWordPtNodePos which is used for bigram
void initAsRoot(const int rootPtNodeArrayPos, const int prevWordPtNodePos) {
- mIsUsed = true;
mIsCachedForNextSuggestion = false;
mDicNodeProperties.init(rootPtNodeArrayPos, prevWordPtNodePos);
mDicNodeState.init();
@@ -116,7 +113,6 @@ class DicNode {
// Init for root with previous word
void initAsRootWithPreviousWord(const DicNode *const dicNode, const int rootPtNodeArrayPos) {
- mIsUsed = true;
mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
mDicNodeProperties.init(rootPtNodeArrayPos, dicNode->mDicNodeProperties.getPtNodePos());
mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState,
@@ -125,10 +121,11 @@ class DicNode {
}
void initAsPassingChild(DicNode *parentDicNode) {
- mIsUsed = true;
mIsCachedForNextSuggestion = parentDicNode->mIsCachedForNextSuggestion;
- const int parentCodePoint = parentDicNode->getNodeTypedCodePoint();
- mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, parentCodePoint);
+ const int codePoint =
+ parentDicNode->mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(
+ parentDicNode->getNodeCodePointCount());
+ mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, codePoint);
mDicNodeState.initByCopy(&parentDicNode->mDicNodeState);
PROF_NODE_COPY(&parentDicNode->mProfiler, mProfiler);
}
@@ -137,7 +134,6 @@ class DicNode {
const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
const bool hasChildren, const bool isBlacklistedOrNotAWord,
const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
- mIsUsed = true;
uint16_t newDepth = static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1);
mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
const uint16_t newLeavingDepth = static_cast<uint16_t>(
@@ -150,17 +146,6 @@ class DicNode {
PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
}
- AK_FORCE_INLINE void finalize() {
- mIsUsed = false;
- if (mReleaseListener) {
- mReleaseListener->onReleased(this);
- }
- }
-
- bool isUsed() const {
- return mIsUsed;
- }
-
bool isRoot() const {
return getNodeCodePointCount() == 0;
}
@@ -186,11 +171,6 @@ class DicNode {
mIsCachedForNextSuggestion = true;
}
- // Used to expand the node in DicNodeUtils
- int getNodeTypedCodePoint() const {
- return mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(getNodeCodePointCount());
- }
-
// Check if the current word and the previous word can be considered as a valid multiple word
// suggestion.
bool isValidMultipleWordSuggestion() const {
@@ -261,17 +241,13 @@ class DicNode {
}
bool isTotalInputSizeExceedingLimit() const {
- const int prevWordsLen = mDicNodeState.mDicNodeStateOutput.getPrevWordsLength();
- const int currentWordDepth = getNodeCodePointCount();
// TODO: 3 can be 2? Needs to be investigated.
// TODO: Have a const variable for 3 (or 2)
- return prevWordsLen + currentWordDepth > MAX_WORD_LENGTH - 3;
+ return getTotalNodeCodePointCount() > MAX_WORD_LENGTH - 3;
}
void outputResult(int *dest) const {
- const uint16_t prevWordLength = mDicNodeState.mDicNodeStateOutput.getPrevWordsLength();
- const uint16_t currentDepth = getNodeCodePointCount();
- memmove(dest, getOutputWordBuf(), (prevWordLength + currentDepth) * sizeof(dest[0]));
+ memmove(dest, getOutputWordBuf(), getTotalNodeCodePointCount() * sizeof(dest[0]));
DUMP_WORD_AND_SCORE("OUTPUT");
}
@@ -329,11 +305,6 @@ class DicNode {
return mDicNodeState.mDicNodeStateScoring.getCompoundDistance(languageWeight);
}
- // Used to commit input partially
- int getPrevWordPtNodePos() const {
- return mDicNodeProperties.getPrevWordTerminalPtNodePos();
- }
-
AK_FORCE_INLINE const int *getOutputWordBuf() const {
return mDicNodeState.mDicNodeStateOutput.getCodePointBuf();
}
@@ -396,10 +367,6 @@ class DicNode {
return mDicNodeState.mDicNodeStateScoring.getSpatialDistance();
}
- float getLanguageDistanceForScoring() const {
- return mDicNodeState.mDicNodeStateScoring.getLanguageDistance();
- }
-
// For space-aware gestures, we store the normalized distance at the char index
// that ends the first word of the suggestion. We call this the distance after
// first word.
@@ -407,22 +374,10 @@ class DicNode {
return mDicNodeState.mDicNodeStateScoring.getNormalizedCompoundDistanceAfterFirstWord();
}
- float getLanguageDistanceRatePerWordForScoring() const {
- const float langDist = getLanguageDistanceForScoring();
- const float totalWordCount =
- static_cast<float>(mDicNodeState.mDicNodeStateOutput.getPrevWordCount() + 1);
- return langDist / totalWordCount;
- }
-
float getRawLength() const {
return mDicNodeState.mDicNodeStateScoring.getRawLength();
}
- bool isLessThanOneErrorForScoring() const {
- return mDicNodeState.mDicNodeStateScoring.getEditCorrectionCount()
- + mDicNodeState.mDicNodeStateScoring.getProximityCorrectionCount() <= 1;
- }
-
DoubleLetterLevel getDoubleLetterLevel() const {
return mDicNodeState.mDicNodeStateScoring.getDoubleLetterLevel();
}
@@ -466,10 +421,6 @@ class DicNode {
#endif
}
- void setReleaseListener(DicNodeReleaseListener *releaseListener) {
- mReleaseListener = releaseListener;
- }
-
AK_FORCE_INLINE bool compare(const DicNode *right) const {
// Promote exact matches to prevent them from being pruned.
const bool leftExactMatch = ErrorTypeUtils::isExactMatch(getContainedErrorTypes());
@@ -507,8 +458,6 @@ class DicNode {
DicNodeState mDicNodeState;
// TODO: Remove
bool mIsCachedForNextSuggestion;
- bool mIsUsed;
- DicNodeReleaseListener *mReleaseListener;
AK_FORCE_INLINE int getTotalInputIndex() const {
int index = 0;
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_pool.h b/native/jni/src/suggest/core/dicnode/dic_node_pool.h
new file mode 100644
index 000000000..a660b744f
--- /dev/null
+++ b/native/jni/src/suggest/core/dicnode/dic_node_pool.h
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_DIC_NODE_POOL_H
+#define LATINIME_DIC_NODE_POOL_H
+
+#include <deque>
+#include <unordered_set>
+#include <vector>
+
+#include "defines.h"
+#include "suggest/core/dicnode/dic_node.h"
+
+namespace latinime {
+
+class DicNodePool {
+ public:
+ explicit DicNodePool(const int capacity) : mDicNodes(), mPooledDicNodes() {
+ reset(capacity);
+ }
+
+ void reset(const int capacity) {
+ if (capacity == static_cast<int>(mDicNodes.size())
+ && capacity == static_cast<int>(mPooledDicNodes.size())) {
+ // No need to reset.
+ return;
+ }
+ mDicNodes.resize(capacity);
+ mDicNodes.shrink_to_fit();
+ mPooledDicNodes.clear();
+ for (auto &dicNode : mDicNodes) {
+ mPooledDicNodes.emplace_back(&dicNode);
+ }
+ }
+
+ // Get a DicNode instance from the pool. The instance has to be returned by returnInstance().
+ DicNode *getInstance() {
+ if (mPooledDicNodes.empty()) {
+ return nullptr;
+ }
+ DicNode *const dicNode = mPooledDicNodes.back();
+ mPooledDicNodes.pop_back();
+ return dicNode;
+ }
+
+ // Return an instance that has been removed from the pool by getInstance() to the pool. The
+ // instance must not be used after returning without getInstance().
+ void placeBackInstance(DicNode *dicNode) {
+ mPooledDicNodes.emplace_back(dicNode);
+ }
+
+ void dump() const {
+ AKLOGI("\n\n\n\n\n===========================");
+ std::unordered_set<const DicNode*> usedDicNodes;
+ for (const auto &dicNode : mDicNodes) {
+ usedDicNodes.insert(&dicNode);
+ }
+ for (const auto &dicNodePtr : mPooledDicNodes) {
+ usedDicNodes.erase(dicNodePtr);
+ }
+ for (const auto &usedDicNodePtr : usedDicNodes) {
+ usedDicNodePtr->dump("DIC_NODE_POOL: ");
+ }
+ AKLOGI("===========================\n\n\n\n\n");
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePool);
+
+ std::vector<DicNode> mDicNodes;
+ std::deque<DicNode*> mPooledDicNodes;
+};
+} // namespace latinime
+#endif // LATINIME_DIC_NODE_POOL_H
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 213b1b968..7b753f2e4 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
@@ -23,38 +23,30 @@
#include "defines.h"
#include "suggest/core/dicnode/dic_node.h"
-#include "suggest/core/dicnode/dic_node_release_listener.h"
+#include "suggest/core/dicnode/dic_node_pool.h"
namespace latinime {
-class DicNodePriorityQueue : public DicNodeReleaseListener {
+class DicNodePriorityQueue {
public:
AK_FORCE_INLINE explicit DicNodePriorityQueue(const int capacity)
- : mCapacity(capacity), mMaxSize(capacity), mDicNodesBuf(),
- mUnusedNodeIndices(), mNextUnusedNodeId(0), mDicNodesQueue() {
- mDicNodesBuf.resize(mCapacity + 1);
- mUnusedNodeIndices.resize(mCapacity + 1);
- clearAndResizeToCapacity();
+ : mMaxSize(capacity), mDicNodesQueue(), mDicNodePool(capacity) {
+ clear();
}
// Non virtual inline destructor -- never inherit this class
AK_FORCE_INLINE ~DicNodePriorityQueue() {}
- int getSize() const {
+ AK_FORCE_INLINE int getSize() const {
return static_cast<int>(mDicNodesQueue.size());
}
- int getMaxSize() const {
+ AK_FORCE_INLINE int getMaxSize() const {
return mMaxSize;
}
AK_FORCE_INLINE void setMaxSize(const int maxSize) {
- ASSERT(maxSize <= mCapacity);
- mMaxSize = std::min(maxSize, mCapacity);
- }
-
- AK_FORCE_INLINE void clearAndResizeToCapacity() {
- clearAndResize(mCapacity);
+ mMaxSize = maxSize;
}
AK_FORCE_INLINE void clear() {
@@ -62,25 +54,32 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
}
AK_FORCE_INLINE void clearAndResize(const int maxSize) {
- ASSERT(maxSize <= mCapacity);
+ mMaxSize = maxSize;
while (!mDicNodesQueue.empty()) {
mDicNodesQueue.pop();
}
- setMaxSize(maxSize);
- for (int i = 0; i < mCapacity + 1; ++i) {
- mDicNodesBuf[i].finalize();
- mDicNodesBuf[i].setReleaseListener(this);
- mUnusedNodeIndices[i] = (i == mCapacity) ? NOT_A_NODE_ID : (i + 1);
- }
- mNextUnusedNodeId = 0;
+ mDicNodePool.reset(mMaxSize + 1);
}
- // Copy
- AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode) {
- return copyPush(dicNode, mMaxSize);
+ AK_FORCE_INLINE void copyPush(const DicNode *const dicNode) {
+ DicNode *const pooledDicNode = newDicNode(dicNode);
+ if (!pooledDicNode) {
+ return;
+ }
+ if (getSize() < mMaxSize) {
+ mDicNodesQueue.push(pooledDicNode);
+ return;
+ }
+ if (betterThanWorstDicNode(pooledDicNode)) {
+ mDicNodePool.placeBackInstance(mDicNodesQueue.top());
+ mDicNodesQueue.pop();
+ mDicNodesQueue.push(pooledDicNode);
+ return;
+ }
+ mDicNodePool.placeBackInstance(pooledDicNode);
}
- AK_FORCE_INLINE void copyPop(DicNode *dest) {
+ AK_FORCE_INLINE void copyPop(DicNode *const dest) {
if (mDicNodesQueue.empty()) {
ASSERT(false);
return;
@@ -89,34 +88,16 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
if (dest) {
DicNodeUtils::initByCopy(node, dest);
}
- node->finalize();
+ mDicNodePool.placeBackInstance(node);
mDicNodesQueue.pop();
}
- 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
- return;
- }
- mUnusedNodeIndices[index] = mNextUnusedNodeId;
- mNextUnusedNodeId = index;
- ASSERT(index >= 0 && index < (mCapacity + 1));
- }
-
- AK_FORCE_INLINE void dump() const {
- AKLOGI("\n\n\n\n\n===========================");
- for (int i = 0; i < mCapacity + 1; ++i) {
- if (mDicNodesBuf[i].isUsed()) {
- mDicNodesBuf[i].dump("QUEUE: ");
- }
- }
- AKLOGI("===========================\n\n\n\n\n");
+ AK_FORCE_INLINE void dump() {
+ mDicNodePool.dump();
}
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePriorityQueue);
- static const int NOT_A_NODE_ID = -1;
AK_FORCE_INLINE static bool compareDicNode(const DicNode *const left,
const DicNode *const right) {
@@ -124,26 +105,15 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
}
struct DicNodeComparator {
- bool operator ()(DicNode *left, DicNode *right) {
+ bool operator ()(const DicNode *left, const DicNode *right) const {
return compareDicNode(left, right);
}
};
typedef std::priority_queue<DicNode *, std::vector<DicNode *>, DicNodeComparator> DicNodesQueue;
- const int mCapacity;
int mMaxSize;
- std::vector<DicNode> mDicNodesBuf; // of each element of mDicNodesBuf respectively
- std::vector<int> mUnusedNodeIndices;
- int mNextUnusedNodeId;
DicNodesQueue mDicNodesQueue;
-
- inline bool isFull(const int maxSize) const {
- return getSize() >= maxSize;
- }
-
- AK_FORCE_INLINE void pop() {
- copyPop(nullptr);
- }
+ DicNodePool mDicNodePool;
AK_FORCE_INLINE bool betterThanWorstDicNode(const DicNode *const dicNode) const {
DicNode *worstNode = mDicNodesQueue.top();
@@ -153,61 +123,13 @@ class DicNodePriorityQueue : public DicNodeReleaseListener {
return compareDicNode(dicNode, worstNode);
}
- AK_FORCE_INLINE DicNode *searchEmptyDicNode() {
- if (mCapacity == 0) {
- return nullptr;
- }
- if (mNextUnusedNodeId == NOT_A_NODE_ID) {
- AKLOGI("No unused node found.");
- for (int i = 0; i < mCapacity + 1; ++i) {
- AKLOGI("Dump node availability, %d, %d, %d",
- i, mDicNodesBuf[i].isUsed(), mUnusedNodeIndices[i]);
- }
- ASSERT(false);
- return nullptr;
- }
- DicNode *dicNode = &mDicNodesBuf[mNextUnusedNodeId];
- markNodeAsUsed(dicNode);
- return dicNode;
- }
-
- AK_FORCE_INLINE void markNodeAsUsed(DicNode *dicNode) {
- const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]);
- mNextUnusedNodeId = mUnusedNodeIndices[index];
- mUnusedNodeIndices[index] = NOT_A_NODE_ID;
- ASSERT(index >= 0 && index < (mCapacity + 1));
- }
-
- AK_FORCE_INLINE DicNode *pushPoolNodeWithMaxSize(DicNode *dicNode, const int maxSize) {
- if (!dicNode) {
- return nullptr;
- }
- if (!isFull(maxSize)) {
- mDicNodesQueue.push(dicNode);
- return dicNode;
- }
- if (betterThanWorstDicNode(dicNode)) {
- pop();
- mDicNodesQueue.push(dicNode);
- return dicNode;
- }
- dicNode->finalize();
- return nullptr;
- }
-
- // Copy
- AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode, const int maxSize) {
- return pushPoolNodeWithMaxSize(newDicNode(dicNode), maxSize);
- }
-
AK_FORCE_INLINE DicNode *newDicNode(const DicNode *const dicNode) {
- DicNode *newNode = searchEmptyDicNode();
+ DicNode *newNode = mDicNodePool.getInstance();
if (newNode) {
DicNodeUtils::initByCopy(dicNode, newNode);
}
return newNode;
}
-
};
} // namespace latinime
#endif // LATINIME_DIC_NODE_PRIORITY_QUEUE_H
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
deleted file mode 100644
index c3f432951..000000000
--- a/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef LATINIME_DIC_NODE_RELEASE_LISTENER_H
-#define LATINIME_DIC_NODE_RELEASE_LISTENER_H
-
-#include "defines.h"
-
-namespace latinime {
-
-class DicNode;
-
-class DicNodeReleaseListener {
- public:
- DicNodeReleaseListener() {}
- virtual ~DicNodeReleaseListener() {}
- virtual void onReleased(const DicNode *dicNode) = 0;
- private:
- DISALLOW_COPY_AND_ASSIGN(DicNodeReleaseListener);
-};
-} // namespace latinime
-#endif // LATINIME_DIC_NODE_RELEASE_LISTENER_H
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 6b8dc8c96..089d4467f 100644
--- a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
+++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
@@ -49,15 +49,14 @@ class DicNodesCache {
AK_FORCE_INLINE void reset(const int nextActiveSize, const int terminalSize) {
mInputIndex = 0;
mLastCachedInputIndex = 0;
- // We want to use the max capacity for the current active dic node queue.
- mActiveDicNodes->clearAndResizeToCapacity();
- // nextActiveSize is used to limit the next iteration's active dic node size.
+ // The size of current active DicNode queue doesn't have to be changed.
+ mActiveDicNodes->clear();
+ // nextActiveSize is used to limit the next iteration's active DicNode size.
const int nextActiveSizeFittingToTheCapacity = std::min(nextActiveSize, getCacheCapacity());
mNextActiveDicNodes->clearAndResize(nextActiveSizeFittingToTheCapacity);
mTerminalDicNodes->clearAndResize(terminalSize);
- // We want to use the max capacity for the cached dic nodes that will be used for the
- // continuous suggestion.
- mCachedDicNodesForContinuousSuggestion->clearAndResizeToCapacity();
+ // The size of cached DicNode queue doesn't have to be changed.
+ mCachedDicNodesForContinuousSuggestion->clear();
}
AK_FORCE_INLINE void continueSearch() {
@@ -95,8 +94,8 @@ class DicNodesCache {
mActiveDicNodes->copyPush(dicNode);
}
- AK_FORCE_INLINE bool copyPushContinue(DicNode *dicNode) {
- return mCachedDicNodesForContinuousSuggestion->copyPush(dicNode);
+ AK_FORCE_INLINE void copyPushContinue(DicNode *dicNode) {
+ mCachedDicNodesForContinuousSuggestion->copyPush(dicNode);
}
AK_FORCE_INLINE void copyPushNextActive(DicNode *dicNode) {
diff --git a/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java
new file mode 100644
index 000000000..ff1103e4f
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2011 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.content.Context;
+import android.content.res.Resources;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.RichInputMethodManager;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+@SmallTest
+public class SpacebarLanguagetUtilsTests extends AndroidTestCase {
+ // All input method subtypes of LatinIME.
+ private final ArrayList<InputMethodSubtype> mSubtypesList = CollectionUtils.newArrayList();
+
+ private RichInputMethodManager mRichImm;
+ private Resources mRes;
+
+ InputMethodSubtype EN_US;
+ InputMethodSubtype EN_GB;
+ InputMethodSubtype ES_US;
+ InputMethodSubtype FR;
+ InputMethodSubtype FR_CA;
+ InputMethodSubtype FR_CH;
+ InputMethodSubtype DE;
+ InputMethodSubtype DE_CH;
+ InputMethodSubtype ZZ;
+ InputMethodSubtype DE_QWERTY;
+ InputMethodSubtype FR_QWERTZ;
+ InputMethodSubtype EN_US_AZERTY;
+ InputMethodSubtype EN_UK_DVORAK;
+ InputMethodSubtype ES_US_COLEMAK;
+ InputMethodSubtype ZZ_AZERTY;
+ InputMethodSubtype ZZ_PC;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ final Context context = getContext();
+ RichInputMethodManager.init(context);
+ mRichImm = RichInputMethodManager.getInstance();
+ mRes = context.getResources();
+ SubtypeLocaleUtils.init(context);
+
+ final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme();
+ final int subtypeCount = imi.getSubtypeCount();
+ for (int index = 0; index < subtypeCount; index++) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(index);
+ mSubtypesList.add(subtype);
+ }
+
+ EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.US.toString(), "qwerty");
+ EN_GB = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.UK.toString(), "qwerty");
+ ES_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "es_US", "spanish");
+ FR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.FRENCH.toString(), "azerty");
+ FR_CA = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.CANADA_FRENCH.toString(), "qwerty");
+ FR_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "fr_CH", "swiss");
+ DE = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ Locale.GERMAN.toString(), "qwertz");
+ DE_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "de_CH", "swiss");
+ ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
+ DE_QWERTY = AdditionalSubtypeUtils.createAdditionalSubtype(
+ Locale.GERMAN.toString(), "qwerty", null);
+ FR_QWERTZ = AdditionalSubtypeUtils.createAdditionalSubtype(
+ Locale.FRENCH.toString(), "qwertz", null);
+ EN_US_AZERTY = AdditionalSubtypeUtils.createAdditionalSubtype(
+ Locale.US.toString(), "azerty", null);
+ EN_UK_DVORAK = AdditionalSubtypeUtils.createAdditionalSubtype(
+ Locale.UK.toString(), "dvorak", null);
+ ES_US_COLEMAK = AdditionalSubtypeUtils.createAdditionalSubtype(
+ "es_US", "colemak", null);
+ ZZ_AZERTY = AdditionalSubtypeUtils.createAdditionalSubtype(
+ SubtypeLocaleUtils.NO_LANGUAGE, "azerty", null);
+ ZZ_PC = AdditionalSubtypeUtils.createAdditionalSubtype(
+ SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty", null);
+ }
+
+ public void testAllFullDisplayNameForSpacebar() {
+ for (final InputMethodSubtype subtype : mSubtypesList) {
+ final String subtypeName = SubtypeLocaleUtils
+ .getSubtypeDisplayNameInSystemLocale(subtype);
+ final String spacebarText = SpacebarLanguageUtils.getFullDisplayName(subtype);
+ final String languageName = SubtypeLocaleUtils
+ .getSubtypeLocaleDisplayName(subtype.getLocale());
+ if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+ assertFalse(subtypeName, spacebarText.contains(languageName));
+ } else {
+ assertTrue(subtypeName, spacebarText.contains(languageName));
+ }
+ }
+ }
+
+ public void testAllMiddleDisplayNameForSpacebar() {
+ for (final InputMethodSubtype subtype : mSubtypesList) {
+ final String subtypeName = SubtypeLocaleUtils
+ .getSubtypeDisplayNameInSystemLocale(subtype);
+ final String spacebarText = SpacebarLanguageUtils.getMiddleDisplayName(subtype);
+ if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+ assertEquals(subtypeName,
+ SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype), spacebarText);
+ } else {
+ final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
+ assertEquals(subtypeName,
+ SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage()),
+ spacebarText);
+ }
+ }
+ }
+
+ // InputMethodSubtype's display name for spacebar text in its locale.
+ // isAdditionalSubtype (T=true, F=false)
+ // 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
+ protected Void job(final Resources res) {
+ assertEquals("en_US", "English (US)",
+ SpacebarLanguageUtils.getFullDisplayName(EN_US));
+ assertEquals("en_GB", "English (UK)",
+ SpacebarLanguageUtils.getFullDisplayName(EN_GB));
+ assertEquals("es_US", "Español (EE.UU.)",
+ SpacebarLanguageUtils.getFullDisplayName(ES_US));
+ assertEquals("fr", "Français",
+ SpacebarLanguageUtils.getFullDisplayName(FR));
+ assertEquals("fr_CA", "Français (Canada)",
+ SpacebarLanguageUtils.getFullDisplayName(FR_CA));
+ assertEquals("fr_CH", "Français (Suisse)",
+ SpacebarLanguageUtils.getFullDisplayName(FR_CH));
+ assertEquals("de", "Deutsch",
+ SpacebarLanguageUtils.getFullDisplayName(DE));
+ assertEquals("de_CH", "Deutsch (Schweiz)",
+ SpacebarLanguageUtils.getFullDisplayName(DE_CH));
+ assertEquals("zz", "QWERTY",
+ SpacebarLanguageUtils.getFullDisplayName(ZZ));
+
+ assertEquals("en_US", "English",
+ SpacebarLanguageUtils.getMiddleDisplayName(EN_US));
+ assertEquals("en_GB", "English",
+ SpacebarLanguageUtils.getMiddleDisplayName(EN_GB));
+ assertEquals("es_US", "Español",
+ SpacebarLanguageUtils.getMiddleDisplayName(ES_US));
+ assertEquals("fr", "Français",
+ SpacebarLanguageUtils.getMiddleDisplayName(FR));
+ assertEquals("fr_CA", "Français",
+ SpacebarLanguageUtils.getMiddleDisplayName(FR_CA));
+ assertEquals("fr_CH", "Français",
+ SpacebarLanguageUtils.getMiddleDisplayName(FR_CH));
+ assertEquals("de", "Deutsch",
+ SpacebarLanguageUtils.getMiddleDisplayName(DE));
+ assertEquals("de_CH", "Deutsch",
+ SpacebarLanguageUtils.getMiddleDisplayName(DE_CH));
+ assertEquals("zz", "QWERTY",
+ SpacebarLanguageUtils.getMiddleDisplayName(ZZ));
+ return null;
+ }
+ };
+
+ private final RunInLocale<Void> testsAdditionalSubtypesForSpacebar = new RunInLocale<Void>() {
+ @Override
+ protected Void job(final Resources res) {
+ assertEquals("fr qwertz", "Français",
+ SpacebarLanguageUtils.getFullDisplayName(FR_QWERTZ));
+ assertEquals("de qwerty", "Deutsch",
+ SpacebarLanguageUtils.getFullDisplayName(DE_QWERTY));
+ assertEquals("en_US azerty", "English (US)",
+ SpacebarLanguageUtils.getFullDisplayName(EN_US_AZERTY));
+ assertEquals("en_UK dvorak", "English (UK)",
+ SpacebarLanguageUtils.getFullDisplayName(EN_UK_DVORAK));
+ assertEquals("es_US colemak", "Español (EE.UU.)",
+ SpacebarLanguageUtils.getFullDisplayName(ES_US_COLEMAK));
+ assertEquals("zz azerty", "AZERTY",
+ SpacebarLanguageUtils.getFullDisplayName(ZZ_AZERTY));
+ assertEquals("zz pc", "PC",
+ SpacebarLanguageUtils.getFullDisplayName(ZZ_PC));
+
+ assertEquals("fr qwertz", "Français",
+ SpacebarLanguageUtils.getMiddleDisplayName(FR_QWERTZ));
+ assertEquals("de qwerty", "Deutsch",
+ SpacebarLanguageUtils.getMiddleDisplayName(DE_QWERTY));
+ assertEquals("en_US azerty", "English",
+ SpacebarLanguageUtils.getMiddleDisplayName(EN_US_AZERTY));
+ assertEquals("en_UK dvorak", "English",
+ SpacebarLanguageUtils.getMiddleDisplayName(EN_UK_DVORAK));
+ assertEquals("es_US colemak", "Español",
+ SpacebarLanguageUtils.getMiddleDisplayName(ES_US_COLEMAK));
+ assertEquals("zz azerty", "AZERTY",
+ SpacebarLanguageUtils.getMiddleDisplayName(ZZ_AZERTY));
+ assertEquals("zz pc", "PC",
+ SpacebarLanguageUtils.getMiddleDisplayName(ZZ_PC));
+ return null;
+ }
+ };
+
+ public void testPredefinedSubtypesForSpacebarInEnglish() {
+ testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
+ }
+
+ public void testAdditionalSubtypeForSpacebarInEnglish() {
+ testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
+ }
+
+ public void testPredefinedSubtypesForSpacebarInFrench() {
+ testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
+ }
+
+ public void testAdditionalSubtypeForSpacebarInFrench() {
+ testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
index eb8a61a16..ee345905c 100644
--- a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
@@ -123,12 +123,23 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
assertEquals("en_US", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_US));
assertEquals("en_GB", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_GB));
assertEquals("es_US", "spanish", SubtypeLocaleUtils.getKeyboardLayoutSetName(ES_US));
- assertEquals("fr ", "azerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR));
+ assertEquals("fr", "azerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR));
assertEquals("fr_CA", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CA));
assertEquals("fr_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CH));
- assertEquals("de ", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE));
+ assertEquals("de", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE));
assertEquals("de_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_CH));
- assertEquals("zz ", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ));
+ assertEquals("zz", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ));
+
+ assertEquals("de qwerty", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_QWERTY));
+ assertEquals("fr qwertz", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_QWERTZ));
+ assertEquals("en_US azerty", "azerty",
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_US_AZERTY));
+ assertEquals("en_UK dvorak", "dvorak",
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_UK_DVORAK));
+ assertEquals("es_US colemak", "colemak",
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(ES_US_COLEMAK));
+ assertEquals("zz azerty", "azerty",
+ SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ_AZERTY));
}
// InputMethodSubtype's display name in system locale (en_US).
@@ -161,17 +172,17 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_GB));
assertEquals("es_US", "Spanish (US)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US));
- assertEquals("fr ", "French",
+ assertEquals("fr", "French",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR));
assertEquals("fr_CA", "French (Canada)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CA));
assertEquals("fr_CH", "French (Switzerland)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CH));
- assertEquals("de ", "German",
+ assertEquals("de", "German",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE));
assertEquals("de_CH", "German (Switzerland)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH));
- assertEquals("zz ", "Alphabet (QWERTY)",
+ assertEquals("zz", "Alphabet (QWERTY)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ));
return null;
}
@@ -183,17 +194,19 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
final RunInLocale<Void> tests = new RunInLocale<Void>() {
@Override
protected Void job(final Resources res) {
- assertEquals("fr qwertz", "French (QWERTZ)",
+ assertEquals("fr qwertz", "French (QWERTZ)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_QWERTZ));
- assertEquals("de qwerty", "German (QWERTY)",
+ assertEquals("de qwerty", "German (QWERTY)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_QWERTY));
assertEquals("en_US azerty", "English (US) (AZERTY)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US_AZERTY));
- assertEquals("en_UK dvorak", "English (UK) (Dvorak)",
+ assertEquals("en_UK dvorak","English (UK) (Dvorak)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_UK_DVORAK));
- assertEquals("es_US colemak","Spanish (US) (Colemak)",
+ assertEquals("es_US colemak", "Spanish (US) (Colemak)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US_COLEMAK));
- assertEquals("zz pc", "Alphabet (PC)",
+ assertEquals("zz azerty", "Alphabet (AZERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_AZERTY));
+ assertEquals("zz pc", "Alphabet (PC)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC));
return null;
}
@@ -231,17 +244,17 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_GB));
assertEquals("es_US", "Espagnol (États-Unis)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US));
- assertEquals("fr ", "Français",
+ assertEquals("fr", "Français",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR));
assertEquals("fr_CA", "Français (Canada)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CA));
assertEquals("fr_CH", "Français (Suisse)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CH));
- assertEquals("de ", "Allemand",
+ assertEquals("de", "Allemand",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE));
assertEquals("de_CH", "Allemand (Suisse)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH));
- assertEquals("zz ", "Alphabet latin (QWERTY)",
+ assertEquals("zz", "Alphabet latin (QWERTY)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ));
return null;
}
@@ -253,17 +266,19 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
final RunInLocale<Void> tests = new RunInLocale<Void>() {
@Override
protected Void job(final Resources res) {
- assertEquals("fr qwertz", "Français (QWERTZ)",
+ assertEquals("fr qwertz", "Français (QWERTZ)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_QWERTZ));
- assertEquals("de qwerty", "Allemand (QWERTY)",
+ assertEquals("de qwerty", "Allemand (QWERTY)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_QWERTY));
assertEquals("en_US azerty", "Anglais (États-Unis) (AZERTY)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US_AZERTY));
assertEquals("en_UK dvorak", "Anglais (Royaume-Uni) (Dvorak)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_UK_DVORAK));
- assertEquals("es_US colemak","Espagnol (États-Unis) (Colemak)",
+ assertEquals("es_US colemak", "Espagnol (États-Unis) (Colemak)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US_COLEMAK));
- assertEquals("zz pc", "Alphabet latin (PC)",
+ assertEquals("zz azerty", "Alphabet latin (AZERTY)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_AZERTY));
+ assertEquals("zz pc", "Alphabet latin (PC)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC));
return null;
}
@@ -271,126 +286,6 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
tests.runInLocale(mRes, Locale.FRENCH);
}
- public void testAllFullDisplayNameForSpacebar() {
- for (final InputMethodSubtype subtype : mSubtypesList) {
- final String subtypeName = SubtypeLocaleUtils
- .getSubtypeDisplayNameInSystemLocale(subtype);
- final String spacebarText = SubtypeLocaleUtils.getFullDisplayName(subtype);
- final String languageName = SubtypeLocaleUtils
- .getSubtypeLocaleDisplayName(subtype.getLocale());
- if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
- assertFalse(subtypeName, spacebarText.contains(languageName));
- } else {
- assertTrue(subtypeName, spacebarText.contains(languageName));
- }
- }
- }
-
- public void testAllMiddleDisplayNameForSpacebar() {
- for (final InputMethodSubtype subtype : mSubtypesList) {
- final String subtypeName = SubtypeLocaleUtils
- .getSubtypeDisplayNameInSystemLocale(subtype);
- final String spacebarText = SubtypeLocaleUtils.getMiddleDisplayName(subtype);
- if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
- assertEquals(subtypeName,
- SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype), spacebarText);
- } else {
- final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
- assertEquals(subtypeName,
- SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage()),
- spacebarText);
- }
- }
- }
-
- // InputMethodSubtype's display name for spacebar text in its locale.
- // isAdditionalSubtype (T=true, F=false)
- // 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
- protected Void job(final Resources res) {
- assertEquals("en_US", "English (US)", SubtypeLocaleUtils.getFullDisplayName(EN_US));
- assertEquals("en_GB", "English (UK)", SubtypeLocaleUtils.getFullDisplayName(EN_GB));
- assertEquals("es_US", "Español (EE.UU.)",
- SubtypeLocaleUtils.getFullDisplayName(ES_US));
- assertEquals("fr ", "Français", SubtypeLocaleUtils.getFullDisplayName(FR));
- assertEquals("fr_CA", "Français (Canada)",
- SubtypeLocaleUtils.getFullDisplayName(FR_CA));
- assertEquals("fr_CH", "Français (Suisse)",
- SubtypeLocaleUtils.getFullDisplayName(FR_CH));
- assertEquals("de ", "Deutsch", SubtypeLocaleUtils.getFullDisplayName(DE));
- assertEquals("de_CH", "Deutsch (Schweiz)",
- SubtypeLocaleUtils.getFullDisplayName(DE_CH));
- assertEquals("zz ", "QWERTY", SubtypeLocaleUtils.getFullDisplayName(ZZ));
-
- assertEquals("en_US", "English", SubtypeLocaleUtils.getMiddleDisplayName(EN_US));
- assertEquals("en_GB", "English", SubtypeLocaleUtils.getMiddleDisplayName(EN_GB));
- assertEquals("es_US", "Español", SubtypeLocaleUtils.getMiddleDisplayName(ES_US));
- assertEquals("fr ", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR));
- assertEquals("fr_CA", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR_CA));
- assertEquals("fr_CH", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR_CH));
- assertEquals("de ", "Deutsch", SubtypeLocaleUtils.getMiddleDisplayName(DE));
- assertEquals("de_CH", "Deutsch", SubtypeLocaleUtils.getMiddleDisplayName(DE_CH));
- assertEquals("zz ", "QWERTY", SubtypeLocaleUtils.getMiddleDisplayName(ZZ));
- return null;
- }
- };
-
- private final RunInLocale<Void> testsAdditionalSubtypesForSpacebar = new RunInLocale<Void>() {
- @Override
- protected Void job(final Resources res) {
- assertEquals("fr qwertz", "Français",
- SubtypeLocaleUtils.getFullDisplayName(FR_QWERTZ));
- assertEquals("de qwerty", "Deutsch",
- SubtypeLocaleUtils.getFullDisplayName(DE_QWERTY));
- assertEquals("en_US azerty", "English (US)",
- SubtypeLocaleUtils.getFullDisplayName(EN_US_AZERTY));
- assertEquals("zz azerty", "AZERTY",
- SubtypeLocaleUtils.getFullDisplayName(ZZ_AZERTY));
-
- assertEquals("fr qwertz", "Français",
- SubtypeLocaleUtils.getMiddleDisplayName(FR_QWERTZ));
- assertEquals("de qwerty", "Deutsch",
- SubtypeLocaleUtils.getMiddleDisplayName(DE_QWERTY));
- assertEquals("en_US azerty", "English",
- SubtypeLocaleUtils.getMiddleDisplayName(EN_US_AZERTY));
- assertEquals("zz azerty", "AZERTY",
- SubtypeLocaleUtils.getMiddleDisplayName(ZZ_AZERTY));
- return null;
- }
- };
-
- public void testPredefinedSubtypesForSpacebarInEnglish() {
- testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
- }
-
- public void testAdditionalSubtypeForSpacebarInEnglish() {
- testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
- }
-
- public void testPredefinedSubtypesForSpacebarInFrench() {
- testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
- }
-
- public void testAdditionalSubtypeForSpacebarInFrench() {
- testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
- }
-
public void testIsRtlLanguage() {
// Known Right-to-Left language subtypes.
final InputMethodSubtype ARABIC = mRichImm