diff options
Diffstat (limited to 'java/src/com/android')
14 files changed, 149 insertions, 102 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index afaf2cc57..816a94300 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -716,10 +716,14 @@ public class Key implements Comparable<Key> { return (attrs != null) ? attrs.mAltCode : CODE_UNSPECIFIED; } + public int getIconId() { + return mIconId; + } + public Drawable getIcon(final KeyboardIconsSet iconSet, final int alpha) { final OptionalAttributes attrs = mOptionalAttributes; final int disabledIconId = (attrs != null) ? attrs.mDisabledIconId : ICON_UNDEFINED; - final int iconId = mEnabled ? mIconId : disabledIconId; + final int iconId = mEnabled ? getIconId() : disabledIconId; final Drawable icon = iconSet.getIconDrawable(iconId); if (icon != null) { icon.setAlpha(alpha); @@ -731,7 +735,7 @@ public class Key implements Comparable<Key> { final OptionalAttributes attrs = mOptionalAttributes; final int previewIconId = (attrs != null) ? attrs.mPreviewIconId : ICON_UNDEFINED; return previewIconId != ICON_UNDEFINED - ? iconSet.getIconDrawable(previewIconId) : iconSet.getIconDrawable(mIconId); + ? iconSet.getIconDrawable(previewIconId) : iconSet.getIconDrawable(getIconId()); } public int getWidth() { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java index da8bf7d69..79d088f2e 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -102,7 +102,7 @@ public final class KeyboardIconsSet { return isValidIconId(iconId) ? ICON_NAMES[iconId] : "unknown<" + iconId + ">"; } - static int getIconId(final String name) { + public static int getIconId(final String name) { Integer iconId = sNameToIdsMap.get(name); if (iconId != null) { return iconId; diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index a7008379f..acbd919cd 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -229,7 +229,7 @@ final public class BinaryDictionaryGetter { private static boolean hackCanUseDictionaryFile(final Locale locale, final File f) { try { // Read the version of the file - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(f); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(f, 0, f.length()); final DictionaryHeader header = dictDecoder.readHeader(); final String version = header.mDictionaryOptions.mAttributes.get(VERSION_KEY); diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java index e767e4be9..2dba7131e 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java @@ -28,6 +28,7 @@ import com.android.inputmethod.latin.personalization.PersonalizationHelper; import com.android.inputmethod.latin.personalization.UserHistoryDictionary; import com.android.inputmethod.latin.settings.SettingsValues; import com.android.inputmethod.latin.utils.CollectionUtils; +import com.android.inputmethod.latin.utils.ExecutorUtils; import com.android.inputmethod.latin.utils.LanguageModelParam; import java.io.File; @@ -208,8 +209,7 @@ public class DictionaryFacilitatorForSuggest { if (listener != null) { listener.onUpdateMainDictionaryAvailability(hasMainDictionary()); } - new Thread("InitializeBinaryDictionary") { - @Override + ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() { public void run() { final DictionaryCollection newMainDict = DictionaryFactory.createMainDictionaryFromManager(context, locale); @@ -219,7 +219,7 @@ public class DictionaryFacilitatorForSuggest { } mLatchForWaitingLoadingMainDictionary.countDown(); } - }.start(); + }); } // The main dictionary could have been loaded asynchronously. Don't cache the return value diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index f9ab9419b..c3e33c0c1 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -29,6 +29,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.utils.AsyncResultHolder; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CombinedFormatUtils; +import com.android.inputmethod.latin.utils.ExecutorUtils; import com.android.inputmethod.latin.utils.FileUtils; import com.android.inputmethod.latin.utils.LanguageModelParam; import com.android.inputmethod.latin.utils.PrioritizedSerialExecutor; @@ -80,9 +81,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { private static final ConcurrentHashMap<String, DictionaryUpdateController> sDictNameDictionaryUpdateControllerMap = CollectionUtils.newConcurrentHashMap(); - private static final ConcurrentHashMap<String, PrioritizedSerialExecutor> - sDictNameExecutorMap = CollectionUtils.newConcurrentHashMap(); - /** The application context. */ protected final Context mContext; @@ -163,33 +161,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return recorder; } - /** - * Gets the executor for the given dictionary name. - */ - private static PrioritizedSerialExecutor getExecutor(final String dictName) { - PrioritizedSerialExecutor executor = sDictNameExecutorMap.get(dictName); - if (executor == null) { - synchronized(sDictNameExecutorMap) { - executor = new PrioritizedSerialExecutor(); - sDictNameExecutorMap.put(dictName, executor); - } - } - return executor; - } - - /** - * Shutdowns all executors and removes all executors from the executor map for testing. - */ - @UsedForTesting - public static void shutdownAllExecutors() { - synchronized(sDictNameExecutorMap) { - for (final PrioritizedSerialExecutor executor : sDictNameExecutorMap.values()) { - executor.shutdown(); - sDictNameExecutorMap.remove(executor); - } - } - } - private static AbstractDictionaryWriter getDictionaryWriter( final boolean isDynamicPersonalizationDictionary) { if (isDynamicPersonalizationDictionary) { @@ -243,10 +214,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ @Override public void close() { - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { - if (mBinaryDictionary!= null) { + if (mBinaryDictionary != null) { mBinaryDictionary.close(); mBinaryDictionary = null; } @@ -256,7 +227,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { protected void closeBinaryDictionary() { // Ensure that no other threads are accessing the local binary dictionary. - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { if (mBinaryDictionary != null) { @@ -287,7 +258,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } protected void clear() { - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { if (mDictionaryWriter == null) { @@ -331,7 +302,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * Check whether GC is needed and run GC if required. */ protected void runGCIfRequired(final boolean mindsBlockByGC) { - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { runGCIfRequiredInternalLocked(mindsBlockByGC); @@ -344,7 +315,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) { if (setProcessingLargeTaskIfNot()) { // Run GC after currently existing time sensitive operations. - getExecutor(mDictName).executePrioritized(new Runnable() { + ExecutorUtils.getExecutor(mDictName).executePrioritized(new Runnable() { @Override public void run() { try { @@ -368,7 +339,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { Log.w(TAG, "addWordDynamically is called for non-updatable dictionary: " + mDictName); return; } - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); @@ -388,7 +359,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { + mDictName); return; } - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); @@ -406,7 +377,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { + mDictName); return; } - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); @@ -430,7 +401,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { "dictionary: " + mDictName); return; } - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { final boolean locked = setProcessingLargeTaskIfNot(); @@ -461,7 +432,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } final AsyncResultHolder<ArrayList<SuggestedWordInfo>> holder = new AsyncResultHolder<ArrayList<SuggestedWordInfo>>(); - getExecutor(mDictName).executePrioritized(new Runnable() { + ExecutorUtils.getExecutor(mDictName).executePrioritized(new Runnable() { @Override public void run() { if (mBinaryDictionary == null) { @@ -500,7 +471,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return false; } final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<Boolean>(); - getExecutor(mDictName).executePrioritized(new Runnable() { + ExecutorUtils.getExecutor(mDictName).executePrioritized(new Runnable() { @Override public void run() { holder.set(isValidWordLocked(word)); @@ -560,7 +531,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { // swapping in the new one. // TODO: Ensure multi-thread assignment of mBinaryDictionary. final BinaryDictionary oldBinaryDictionary = mBinaryDictionary; - getExecutor(mDictName).executePrioritized(new Runnable() { + ExecutorUtils.getExecutor(mDictName).executePrioritized(new Runnable() { @Override public void run() { mBinaryDictionary = newBinaryDictionary; @@ -662,7 +633,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { private final void reloadDictionary() { // Ensure that only one thread attempts to read or write to the shared binary dictionary // file at the same time. - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { try { @@ -696,7 +667,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { // If we just loaded the binary dictionary, then mBinaryDictionary is not // up-to-date yet so it's useless to test it right away. Schedule the check // for right after it's loaded instead. - getExecutor(mDictName).executePrioritized(new Runnable() { + ExecutorUtils.getExecutor(mDictName).executePrioritized(new Runnable() { @Override public void run() { if (mBinaryDictionary != null && !(isValidDictionary() @@ -736,7 +707,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } }; final Runnable oldTask = mUnfinishedFlushingTask.getAndSet(newTask); - getExecutor(mDictName).replaceAndExecute(oldTask, newTask); + ExecutorUtils.getExecutor(mDictName).replaceAndExecute(oldTask, newTask); } /** @@ -757,7 +728,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @UsedForTesting public boolean isInUnderlyingBinaryDictionaryForTests(final String word) { final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<Boolean>(); - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { if (mDictType == Dictionary.TYPE_USER_HISTORY) { @@ -771,7 +742,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @UsedForTesting public void waitAllTasksForTests() { final CountDownLatch countDownLatch = new CountDownLatch(1); - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { countDownLatch.countDown(); @@ -787,7 +758,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @UsedForTesting public void dumpAllWordsForDebug() { reloadDictionaryIfRequired(); - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { Log.d(TAG, "Dump dictionary: " + mDictName); diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index abf831a28..5e144106f 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -147,6 +147,8 @@ public final class Suggest { } } + final boolean isPrediction = !wordComposer.isComposingWord(); + // We allow auto-correction if we have a whitelisted word, or if the word is not a valid // word of more than 1 char, except if the first suggestion is the same as the typed string // because in this case if it's strong enough to auto-correct that will mistakenly designate @@ -165,7 +167,7 @@ public final class Suggest { // same time, it feels wrong that the SuggestedWord object includes information about // the current settings. It may also be useful to know, when the setting is off, whether // the word *would* have been auto-corrected. - if (!isCorrectionEnabled || !allowsToBeAutoCorrected || !wordComposer.isComposingWord() + if (!isCorrectionEnabled || !allowsToBeAutoCorrected || isPrediction || suggestionsSet.isEmpty() || wordComposer.hasDigits() || wordComposer.isMostlyCaps() || wordComposer.isResumed() || !mDictionaryFacilitator.hasMainDictionary() @@ -225,10 +227,9 @@ public final class Suggest { // TODO: this first argument is lying. If this is a whitelisted word which is an // actual word, it says typedWordValid = false, which looks wrong. We should either // rename the attribute or change the value. - !allowsToBeAutoCorrected /* typedWordValid */, + !isPrediction && !allowsToBeAutoCorrected /* typedWordValid */, hasAutoCorrection, /* willAutoCorrect */ - false /* isObsoleteSuggestions */, - !wordComposer.isComposingWord() /* isPrediction */, sequenceNumber)); + false /* isObsoleteSuggestions */, isPrediction, sequenceNumber)); } // Retrieves suggestions for the batch input diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 46df3e88c..06bc90c97 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -69,7 +69,7 @@ public class SuggestedWords { final boolean isPrediction, final int sequenceNumber) { this(suggestedWordInfoList, rawSuggestions, - suggestedWordInfoList.isEmpty() ? null + (suggestedWordInfoList.isEmpty() || isPrediction) ? null : suggestedWordInfoList.get(INDEX_OF_TYPED_WORD).mWord, typedWordValid, willAutoCorrect, isObsoleteSuggestions, isPrediction, sequenceNumber); diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 045d06f0e..f2f9f1e68 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -1360,10 +1360,12 @@ public final class InputLogic { }}); } else { // We found suggestion spans in the word. We'll create the SuggestedWords out of - // them, and make willAutoCorrect false. + // them, and make willAutoCorrect false. We make typedWordValid false, because the + // color of the word in the suggestion strip changes according to this parameter, + // and false gives the correct color. final SuggestedWords suggestedWords = new SuggestedWords(suggestions, null /* rawSuggestions */, typedWord, - true /* typedWordValid */, false /* willAutoCorrect */, + false /* typedWordValid */, false /* willAutoCorrect */, false /* isObsoleteSuggestions */, false /* isPrediction */, SuggestedWords.NOT_A_SEQUENCE_NUMBER); mIsAutoCorrectionIndicatorOn = false; diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java index b534ebeff..25e1bcd25 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java @@ -357,7 +357,7 @@ public final class BinaryDictDecoderUtils { * @return true if it's a binary dictionary, false otherwise */ public static boolean isBinaryDictionary(final File file) { - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, 0, file.length()); if (dictDecoder == null) { return false; } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 989ca4b2f..90e7400fb 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -237,7 +237,7 @@ public final class BinaryDictIOUtils { final File file, final long offset, final long length) throws FileNotFoundException, IOException, UnsupportedFormatException { final byte[] buffer = new byte[HEADER_READING_BUFFER_SIZE]; - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, offset, length, new DictDecoder.DictionaryBufferFactory() { @Override public DictBuffer getDictionaryBuffer(File file) @@ -251,8 +251,7 @@ public final class BinaryDictIOUtils { inStream.close(); } } - } - ); + }); if (dictDecoder == null) { return null; } diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index c7635eff9..9abecbfec 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -326,30 +326,34 @@ public final class FormatSpec { * Returns new dictionary decoder. * * @param dictFile the dictionary file. + * @param offset the offset in the file. + * @param length the length of the file, in bytes. * @param bufferType The type of buffer, as one of USE_* in DictDecoder. * @return new dictionary decoder if the dictionary file exists, otherwise null. */ - public static DictDecoder getDictDecoder(final File dictFile, final int bufferType) { + public static DictDecoder getDictDecoder(final File dictFile, final long offset, + final long length, final int bufferType) { if (dictFile.isDirectory()) { return new Ver4DictDecoder(dictFile, bufferType); } else if (dictFile.isFile()) { - return new Ver2DictDecoder(dictFile, bufferType); + return new Ver2DictDecoder(dictFile, offset, length, bufferType); } return null; } - public static DictDecoder getDictDecoder(final File dictFile, - final DictionaryBufferFactory factory) { + public static DictDecoder getDictDecoder(final File dictFile, final long offset, + final long length, final DictionaryBufferFactory factory) { if (dictFile.isDirectory()) { return new Ver4DictDecoder(dictFile, factory); } else if (dictFile.isFile()) { - return new Ver2DictDecoder(dictFile, factory); + return new Ver2DictDecoder(dictFile, offset, length, factory); } return null; } - public static DictDecoder getDictDecoder(final File dictFile) { - return getDictDecoder(dictFile, DictDecoder.USE_READONLY_BYTEBUFFER); + public static DictDecoder getDictDecoder(final File dictFile, final long offset, + final long length) { + return getDictDecoder(dictFile, offset, length, DictDecoder.USE_READONLY_BYTEBUFFER); } private FormatSpec() { diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java index bf776cfc5..ae1e443c5 100644 --- a/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java @@ -116,13 +116,18 @@ public class Ver2DictDecoder extends AbstractDictDecoder { } protected final File mDictionaryBinaryFile; + protected final long mOffset; + protected final long mLength; // TODO: Remove mBufferFactory and mDictBuffer from this class members because they are now // used only for testing. private final DictionaryBufferFactory mBufferFactory; protected DictBuffer mDictBuffer; - /* package */ Ver2DictDecoder(final File file, final int factoryFlag) { + /* package */ Ver2DictDecoder(final File file, final long offset, final long length, + final int factoryFlag) { mDictionaryBinaryFile = file; + mOffset = offset; + mLength = length; mDictBuffer = null; if ((factoryFlag & MASK_DICTBUFFER) == USE_READONLY_BYTEBUFFER) { mBufferFactory = new DictionaryBufferFromReadOnlyByteBufferFactory(); @@ -135,8 +140,11 @@ public class Ver2DictDecoder extends AbstractDictDecoder { } } - /* package */ Ver2DictDecoder(final File file, final DictionaryBufferFactory factory) { + /* package */ Ver2DictDecoder(final File file, final long offset, final long length, + final DictionaryBufferFactory factory) { mDictionaryBinaryFile = file; + mOffset = offset; + mLength = length; mBufferFactory = factory; } @@ -164,9 +172,9 @@ public class Ver2DictDecoder extends AbstractDictDecoder { public DictionaryHeader readHeader() throws IOException, UnsupportedFormatException { // dictType is not being used in dicttool. Passing an empty string. final BinaryDictionary binaryDictionary = new BinaryDictionary( - mDictionaryBinaryFile.getAbsolutePath(), 0 /* offset */, - mDictionaryBinaryFile.length() /* length */, true /* useFullEditDistance */, - null /* locale */, "" /* dictType */, false /* isUpdatable */); + mDictionaryBinaryFile.getAbsolutePath(), mOffset, mLength, + true /* useFullEditDistance */, null /* locale */, "" /* dictType */, + false /* isUpdatable */); final DictionaryHeader header = binaryDictionary.getHeader(); binaryDictionary.close(); if (header == null) { diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java index 8ea712835..afa8fe3a8 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java @@ -95,9 +95,9 @@ final class SuggestionStripLayoutHelper { private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD); private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan(); - private final int mSuggestionStripOption; + private final int mSuggestionStripOptions; // These constants are the flag values of - // {@link R.styleable#SuggestionStripView_suggestionStripOption} attribute. + // {@link R.styleable#SuggestionStripView_suggestionStripOptions} attribute. private static final int AUTO_CORRECT_BOLD = 0x01; private static final int AUTO_CORRECT_UNDERLINE = 0x02; private static final int VALID_TYPED_WORD_BOLD = 0x04; @@ -122,8 +122,8 @@ final class SuggestionStripLayoutHelper { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SuggestionStripView, defStyle, R.style.SuggestionStripView); - mSuggestionStripOption = a.getInt( - R.styleable.SuggestionStripView_suggestionStripOption, 0); + mSuggestionStripOptions = a.getInt( + R.styleable.SuggestionStripView_suggestionStripOptions, 0); mAlphaObsoleted = ResourceUtils.getFraction(a, R.styleable.SuggestionStripView_alphaObsoleted, 1.0f); mColorValidTypedWord = a.getColor(R.styleable.SuggestionStripView_colorValidTypedWord, 0); @@ -200,22 +200,24 @@ final class SuggestionStripLayoutHelper { return null; } final String word = suggestedWords.getLabel(indexInSuggestedWords); - final boolean isAutoCorrect = indexInSuggestedWords == 1 - && suggestedWords.mWillAutoCorrect; - final boolean isTypedWordValid = indexInSuggestedWords == 0 - && suggestedWords.mTypedWordValid; - if (!isAutoCorrect && !isTypedWordValid) { + // TODO: don't use the index to decide whether this is the auto-correction/typed word, as + // this is brittle + final boolean isAutoCorrection = suggestedWords.mWillAutoCorrect + && indexInSuggestedWords == SuggestedWords.INDEX_OF_AUTO_CORRECTION; + final boolean isTypedWordValid = suggestedWords.mTypedWordValid + && indexInSuggestedWords == SuggestedWords.INDEX_OF_TYPED_WORD; + if (!isAutoCorrection && !isTypedWordValid) { return word; } final int len = word.length(); final Spannable spannedWord = new SpannableString(word); - final int option = mSuggestionStripOption; - if ((isAutoCorrect && (option & AUTO_CORRECT_BOLD) != 0) - || (isTypedWordValid && (option & VALID_TYPED_WORD_BOLD) != 0)) { + final int options = mSuggestionStripOptions; + if ((isAutoCorrection && (options & AUTO_CORRECT_BOLD) != 0) + || (isTypedWordValid && (options & VALID_TYPED_WORD_BOLD) != 0)) { spannedWord.setSpan(BOLD_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); } - if (isAutoCorrect && (option & AUTO_CORRECT_UNDERLINE) != 0) { + if (isAutoCorrection && (options & AUTO_CORRECT_UNDERLINE) != 0) { spannedWord.setSpan(UNDERLINE_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); } return spannedWord; @@ -242,22 +244,23 @@ final class SuggestionStripLayoutHelper { return indexInSuggestedWords; } - private int getSuggestionTextColor(final int indexInSuggestedWords, - final SuggestedWords suggestedWords) { + private int getSuggestionTextColor(final SuggestedWords suggestedWords, + final int indexInSuggestedWords) { final int positionInStrip = getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords); - // TODO: Need to revisit this logic with bigram suggestions - final boolean isSuggested = (indexInSuggestedWords != SuggestedWords.INDEX_OF_TYPED_WORD); + // Use identity for strings, not #equals : it's the typed word if it's the same object + final boolean isTypedWord = + suggestedWords.getWord(indexInSuggestedWords) == suggestedWords.mTypedWord; final int color; if (positionInStrip == mCenterPositionInStrip && suggestedWords.mWillAutoCorrect) { color = mColorAutoCorrect; - } else if (positionInStrip == mCenterPositionInStrip && suggestedWords.mTypedWordValid) { + } else if (isTypedWord && suggestedWords.mTypedWordValid) { color = mColorValidTypedWord; - } else if (isSuggested) { - color = mColorSuggested; - } else { + } else if (isTypedWord) { color = mColorTypedWord; + } else { + color = mColorSuggested; } if (LatinImeLogger.sDBG && suggestedWords.size() > 1) { // If we auto-correct, then the autocorrection is in slot 0 and the typed word @@ -270,7 +273,7 @@ final class SuggestionStripLayoutHelper { } } - if (suggestedWords.mIsObsoleteSuggestions && isSuggested) { + if (suggestedWords.mIsObsoleteSuggestions && !isTypedWord) { return applyAlpha(color, mAlphaObsoleted); } return color; @@ -438,7 +441,7 @@ final class SuggestionStripLayoutHelper { // {@link SuggestionStripView#onClick(View)}. wordView.setTag(indexInSuggestedWords); wordView.setText(getStyledSuggestedWord(suggestedWords, indexInSuggestedWords)); - wordView.setTextColor(getSuggestionTextColor(positionInStrip, suggestedWords)); + wordView.setTextColor(getSuggestionTextColor(suggestedWords, indexInSuggestedWords)); if (SuggestionStripView.DBG) { mDebugInfoViews.get(positionInStrip).setText( suggestedWords.getDebugString(indexInSuggestedWords)); diff --git a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java new file mode 100644 index 000000000..ee9718ad3 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java @@ -0,0 +1,55 @@ +/* + * 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 com.android.inputmethod.annotations.UsedForTesting; + +import java.util.concurrent.ConcurrentHashMap; + +/** + * Utilities to manage executors. + */ +public class ExecutorUtils { + private static final ConcurrentHashMap<String, PrioritizedSerialExecutor> + sExecutorMap = CollectionUtils.newConcurrentHashMap(); + /** + * Gets the executor for the given dictionary name. + */ + public static PrioritizedSerialExecutor getExecutor(final String dictName) { + PrioritizedSerialExecutor executor = sExecutorMap.get(dictName); + if (executor == null) { + synchronized(sExecutorMap) { + executor = new PrioritizedSerialExecutor(); + sExecutorMap.put(dictName, executor); + } + } + return executor; + } + + /** + * Shutdowns all executors and removes all executors from the executor map for testing. + */ + @UsedForTesting + public static void shutdownAllExecutors() { + synchronized(sExecutorMap) { + for (final PrioritizedSerialExecutor executor : sExecutorMap.values()) { + executor.shutdown(); + sExecutorMap.remove(executor); + } + } + } +} |