aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java28
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java14
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java2
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java6
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java69
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java8
-rw-r--r--java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java55
9 files changed, 117 insertions, 75 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
index 4c53b528f..7fff46aaf 100644
--- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
+++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
@@ -25,7 +25,6 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Rect;
-import android.graphics.Typeface;
import android.os.Build;
import android.os.CountDownTimer;
import android.preference.PreferenceManager;
@@ -49,6 +48,8 @@ import android.widget.TextView;
import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard;
import com.android.inputmethod.keyboard.internal.EmojiLayoutParams;
import com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView;
+import com.android.inputmethod.keyboard.internal.KeyDrawParams;
+import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SubtypeSwitcher;
@@ -634,20 +635,23 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
// TODO:
}
- // Hack: These parameters are hacky.
- public void startEmojiPalettes(final String switchToAlphaLabel, final int switchToAlphaColor,
- final float switchToAlphaSize, final Typeface switchToAlphaTypeface) {
+ private static void setupAlphabetKey(final TextView alphabetKey, final String label,
+ final KeyDrawParams params) {
+ alphabetKey.setText(label);
+ alphabetKey.setTextColor(params.mTextColor);
+ alphabetKey.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mLabelSize);
+ alphabetKey.setTypeface(params.mTypeface);
+ }
+
+ public void startEmojiPalettes(final String switchToAlphaLabel,
+ final KeyVisualAttributes keyVisualAttr) {
if (DEBUG_PAGER) {
Log.d(TAG, "allocate emoji palettes memory " + mCurrentPagerPosition);
}
- mAlphabetKeyLeft.setText(switchToAlphaLabel);
- mAlphabetKeyLeft.setTextColor(switchToAlphaColor);
- mAlphabetKeyLeft.setTextSize(TypedValue.COMPLEX_UNIT_PX, switchToAlphaSize);
- mAlphabetKeyLeft.setTypeface(switchToAlphaTypeface);
- mAlphabetKeyRight.setText(switchToAlphaLabel);
- mAlphabetKeyRight.setTextColor(switchToAlphaColor);
- mAlphabetKeyRight.setTextSize(TypedValue.COMPLEX_UNIT_PX, switchToAlphaSize);
- mAlphabetKeyRight.setTypeface(switchToAlphaTypeface);
+ final KeyDrawParams params = new KeyDrawParams();
+ params.updateParams(mEmojiLayoutParams.getActionBarHeight(), keyVisualAttr);
+ setupAlphabetKey(mAlphabetKeyLeft, switchToAlphaLabel, params);
+ setupAlphabetKey(mAlphabetKeyRight, switchToAlphaLabel, params);
mEmojiPager.setAdapter(mEmojiPalettesAdapter);
mEmojiPager.setCurrentItem(mCurrentPagerPosition);
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 6215e2710..f9758634e 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -19,7 +19,6 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
-import android.graphics.Paint;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -31,7 +30,7 @@ import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
import com.android.inputmethod.keyboard.KeyboardLayoutSet.KeyboardLayoutSetException;
import com.android.inputmethod.keyboard.internal.KeyboardState;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.keyboard.internal.KeyboardTextsSet;
import com.android.inputmethod.latin.InputView;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
@@ -81,8 +80,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
private KeyboardState mState;
private KeyboardLayoutSet mKeyboardLayoutSet;
+ // TODO: The following {@link KeyboardTextsSet} should be in {@link KeyboardLayoutSet}.
+ private final KeyboardTextsSet mKeyboardTextsSet = new KeyboardTextsSet();
private SettingsValues mCurrentSettingsValues;
- private Key mSwitchToAlphaKey;
/** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of
* what user actually typed. */
@@ -163,8 +163,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mCurrentSettingsValues = settingsValues;
try {
mState.onLoadKeyboard();
- final Keyboard symbols = mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS);
- mSwitchToAlphaKey = symbols.getKey(Constants.CODE_SWITCH_ALPHA_SYMBOL);
+ mKeyboardTextsSet.setLocale(mSubtypeSwitcher.getCurrentSubtypeLocale());
} catch (KeyboardLayoutSetException e) {
Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause());
LatinImeLogger.logOnException(e.mKeyboardId.toString(), e.getCause());
@@ -290,10 +289,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
@Override
public void setEmojiKeyboard() {
mMainKeyboardFrame.setVisibility(View.GONE);
- final Paint paint = mKeyboardView.newLabelPaint(mSwitchToAlphaKey);
mEmojiPalettesView.startEmojiPalettes(
- mSwitchToAlphaKey.getLabel(), paint.getColor(), paint.getTextSize(),
- paint.getTypeface());
+ mKeyboardTextsSet.getText(KeyboardTextsSet.SWITCH_TO_ALPHA_KEY_LABEL),
+ mKeyboardView.getKeyVisualAttribute());
mEmojiPalettesView.setVisibility(View.VISIBLE);
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index dd3ab9cce..18e51d392 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -146,6 +146,10 @@ public class KeyboardView extends View {
mPaint.setAntiAlias(true);
}
+ public KeyVisualAttributes getKeyVisualAttribute() {
+ return mKeyVisualAttributes;
+ }
+
private static void blendAlpha(final Paint paint, final int alpha) {
final int color = paint.getColor();
paint.setARGB((paint.getAlpha() * alpha) / Constants.Color.ALPHA_OPAQUE,
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java
index 12e063261..d57ea5a94 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java
@@ -73,9 +73,13 @@ public class EmojiLayoutParams {
ll.setLayoutParams(lp);
}
+ public int getActionBarHeight() {
+ return mEmojiActionBarHeight - mBottomPadding;
+ }
+
public void setActionBarProperties(final LinearLayout ll) {
final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ll.getLayoutParams();
- lp.height = mEmojiActionBarHeight - mBottomPadding;
+ lp.height = getActionBarHeight();
ll.setLayoutParams(lp);
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index 89221ba24..976038c10 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -29,6 +29,8 @@ import java.util.Locale;
public final class KeyboardTextsSet {
public static final String PREFIX_TEXT = "!text/";
+ public static final String SWITCH_TO_ALPHA_KEY_LABEL = "label_to_alpha_key";
+
private static final char BACKSLASH = Constants.CODE_BACKSLASH;
private static final int MAX_STRING_REFERENCE_INDIRECTION = 10;
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/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 30b20a335..323256d1c 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -483,12 +483,16 @@ public final class RichInputConnection {
*
* @param start the character index where the selection should start.
* @param end the character index where the selection should end.
- * @return Returns true on success, false if the input connection is no longer valid either when
- * setting the selection or when retrieving the text cache at that point.
+ * @return Returns true on success, false on failure: either the input connection is no longer
+ * valid when setting the selection or when retrieving the text cache at that point, or
+ * invalid arguments were passed.
*/
public boolean setSelection(final int start, final int end) {
if (DEBUG_BATCH_NESTING) checkBatchEdit();
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
+ if (start < 0 || end < 0) {
+ return false;
+ }
mExpectedSelStart = start;
mExpectedSelEnd = end;
if (null != mIC) {
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);
+ }
+ }
+ }
+}