aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod
diff options
context:
space:
mode:
authorJean Chalard <jchalard@google.com>2011-08-16 17:37:18 +0900
committerJean Chalard <jchalard@google.com>2011-08-16 18:13:12 +0900
commita562767a14c7bbac95b25e69e360fc28d6ce9e33 (patch)
treebb18f50cf1a5d0f83a8cab1fce44cefc7431550a /java/src/com/android/inputmethod
parent70b9c5d9913b676f21fe29f795bdb25324509205 (diff)
downloadlatinime-a562767a14c7bbac95b25e69e360fc28d6ce9e33.tar.gz
latinime-a562767a14c7bbac95b25e69e360fc28d6ce9e33.tar.xz
latinime-a562767a14c7bbac95b25e69e360fc28d6ce9e33.zip
Have a pool of dictionaries to check spelling.
The dictionaries and proximities are not thread-safe. In order to be able to check spelling in parallel, make a dictionary pool to call upon when a spelling check is necessary. Bug: 5156851 Change-Id: Ie3796164187dd7b7abf5ccd5d014073d43d74408
Diffstat (limited to 'java/src/com/android/inputmethod')
-rw-r--r--java/src/com/android/inputmethod/keyboard/ProximityInfo.java6
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java61
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java32
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java55
4 files changed, 127 insertions, 27 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 5e73d6300..7190b051d 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -56,12 +56,12 @@ public class ProximityInfo {
computeNearestNeighbors(keyWidth, keys);
}
- public static ProximityInfo getDummyProximityInfo() {
+ public static ProximityInfo createDummyProximityInfo() {
return new ProximityInfo(1, 1, 1, 1, 1, Collections.<Key>emptyList());
}
- public static ProximityInfo getSpellCheckerProximityInfo() {
- final ProximityInfo spellCheckerProximityInfo = getDummyProximityInfo();
+ public static ProximityInfo createSpellCheckerProximityInfo() {
+ final ProximityInfo spellCheckerProximityInfo = createDummyProximityInfo();
spellCheckerProximityInfo.mNativeProximityInfo =
spellCheckerProximityInfo.setProximityInfoNative(
SpellCheckerProximityInfo.ROW_SIZE,
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index d2b6bcdf2..c71841042 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -19,6 +19,7 @@ package com.android.inputmethod.latin.spellcheck;
import android.content.res.Resources;
import android.service.textservice.SpellCheckerService;
import android.service.textservice.SpellCheckerService.Session;
+import android.util.Log;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
@@ -34,8 +35,6 @@ import com.android.inputmethod.latin.WordComposer;
import java.util.Arrays;
import java.util.Collections;
-import java.util.List;
-import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
@@ -45,12 +44,12 @@ import java.util.TreeMap;
*/
public class AndroidSpellCheckerService extends SpellCheckerService {
private static final String TAG = AndroidSpellCheckerService.class.getSimpleName();
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
+ private static final int POOL_SIZE = 2;
private final static String[] emptyArray = new String[0];
- private final ProximityInfo mProximityInfo = ProximityInfo.getSpellCheckerProximityInfo();
- private final Map<String, Dictionary> mDictionaries =
- Collections.synchronizedMap(new TreeMap<String, Dictionary>());
+ private final Map<String, DictionaryPool> mDictionaryPools =
+ Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
@Override
public Session createSession() {
@@ -105,22 +104,32 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
}
}
- private Dictionary getDictionary(final String locale) {
- Dictionary dictionary = mDictionaries.get(locale);
- if (null == dictionary) {
- final Resources resources = getResources();
- final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources);
+ private DictionaryPool getDictionaryPool(final String locale) {
+ DictionaryPool pool = mDictionaryPools.get(locale);
+ if (null == pool) {
final Locale localeObject = Utils.constructLocaleFromString(locale);
- dictionary = DictionaryFactory.createDictionaryFromManager(this, localeObject,
- fallbackResourceId);
- mDictionaries.put(locale, dictionary);
+ pool = new DictionaryPool(POOL_SIZE, this, localeObject);
+ mDictionaryPools.put(locale, pool);
}
- return dictionary;
+ return pool;
+ }
+
+ public DictAndProximity createDictAndProximity(final Locale locale) {
+ final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo();
+ final Resources resources = getResources();
+ final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources);
+ final Dictionary dictionary =
+ DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId);
+ return new DictAndProximity(dictionary, proximityInfo);
}
private class AndroidSpellCheckerSession extends Session {
+ // Immutable, but need the locale which is not available in the constructor yet
+ DictionaryPool mDictionaryPool;
+
@Override
public void onCreate() {
+ mDictionaryPool = getDictionaryPool(getLocale());
}
// Note : this must be reentrant
@@ -132,8 +141,6 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
@Override
public SuggestionsInfo onGetSuggestions(final TextInfo textInfo,
final int suggestionsLimit) {
- final String locale = getLocale();
- final Dictionary dictionary = getDictionary(locale);
final String text = textInfo.getText();
final SuggestionsGatherer suggestionsGatherer =
@@ -153,15 +160,21 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
composer.add(character, proximities,
WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
}
- final boolean isInDict;
- final String[] suggestions;
- synchronized(dictionary) {
- // TODO: make the dictionary reentrant so that we don't have to synchronize here
- dictionary.getWords(composer, suggestionsGatherer, mProximityInfo);
- isInDict = dictionary.isValidWord(text);
- suggestions = suggestionsGatherer.getGatheredSuggestions();
+
+ boolean isInDict = true;
+ try {
+ final DictAndProximity dictInfo = mDictionaryPool.take();
+ dictInfo.mDictionary.getWords(composer, suggestionsGatherer,
+ dictInfo.mProximityInfo);
+ isInDict = dictInfo.mDictionary.isValidWord(text);
+ mDictionaryPool.offer(dictInfo);
+ } catch (InterruptedException e) {
+ // I don't think this can happen.
+ return new SuggestionsInfo(0, new String[0]);
}
+ final String[] suggestions = suggestionsGatherer.getGatheredSuggestions();
+
final int flags =
(isInDict ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY : 0)
| (null != suggestions
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java b/java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java
new file mode 100644
index 000000000..3dbbd40cd
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java
@@ -0,0 +1,32 @@
+/*
+ * 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.spellcheck;
+
+import com.android.inputmethod.latin.Dictionary;
+import com.android.inputmethod.keyboard.ProximityInfo;
+
+/**
+ * A simple container for both a Dictionary and a ProximityInfo.
+ */
+public class DictAndProximity {
+ public final Dictionary mDictionary;
+ public final ProximityInfo mProximityInfo;
+ public DictAndProximity(final Dictionary dictionary, final ProximityInfo proximityInfo) {
+ mDictionary = dictionary;
+ mProximityInfo = proximityInfo;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
new file mode 100644
index 000000000..dfbfcc7f6
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
@@ -0,0 +1,55 @@
+/*
+ * 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.spellcheck;
+
+import android.content.Context;
+
+import java.util.Locale;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * A blocking queue that creates dictionaries up to a certain limit as necessary.
+ */
+public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
+ private final AndroidSpellCheckerService mService;
+ private final int mMaxSize;
+ private final Locale mLocale;
+ private int mSize = 0;
+
+ public DictionaryPool(final int maxSize, final AndroidSpellCheckerService service,
+ final Locale locale) {
+ super();
+ mMaxSize = maxSize;
+ mService = service;
+ mLocale = locale;
+ }
+
+ @Override
+ public DictAndProximity take() throws InterruptedException {
+ final DictAndProximity dict = poll();
+ if (null != dict) return dict;
+ synchronized(this) {
+ if (mSize >= mMaxSize) {
+ // Our pool is already full. Wait until some dictionary is ready.
+ return super.take();
+ } else {
+ ++mSize;
+ return mService.createDictAndProximity(mLocale);
+ }
+ }
+ }
+}