Skip to content
Snippets Groups Projects
Commit fe3c4ef9 authored by Dan Zivkovic's avatar Dan Zivkovic Committed by Android (Google) Code Review
Browse files

Merge "Spell checker uses cache of size 1."

parents 01b02373 29aa3df3
No related branches found
No related tags found
No related merge requests found
...@@ -16,15 +16,11 @@ ...@@ -16,15 +16,11 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import com.android.inputmethod.annotations.UsedForTesting;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import android.util.LruCache;
/** /**
* Cache for dictionary facilitators of multiple locales. * Cache for dictionary facilitators of multiple locales.
...@@ -32,54 +28,20 @@ import android.util.LruCache; ...@@ -32,54 +28,20 @@ import android.util.LruCache;
*/ */
public class DictionaryFacilitatorLruCache { public class DictionaryFacilitatorLruCache {
private static final String TAG = "DictionaryFacilitatorLruCache"; private static final String TAG = "DictionaryFacilitatorLruCache";
private static final int MAX_DICTIONARY_FACILITATOR_COUNT = 3;
private static final int WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS = 1000; private static final int WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS = 1000;
private static final int MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT = 5; private static final int MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT = 5;
/**
* Class extends LruCache. This class tracks cached locales and closes evicted dictionaries by
* overriding entryRemoved.
*/
private static class DictionaryFacilitatorLruCacheInner extends
LruCache<Locale, DictionaryFacilitator> {
private final HashSet<Locale> mCachedLocales;
public DictionaryFacilitatorLruCacheInner(final HashSet<Locale> cachedLocales,
final int maxSize) {
super(maxSize);
mCachedLocales = cachedLocales;
}
@Override
protected void entryRemoved(boolean evicted, Locale key,
DictionaryFacilitator oldValue, DictionaryFacilitator newValue) {
if (oldValue != null && oldValue != newValue) {
oldValue.closeDictionaries();
}
if (key != null && newValue == null) {
// Remove locale from the cache when the dictionary facilitator for the locale is
// evicted and new facilitator is not set for the locale.
mCachedLocales.remove(key);
if (size() >= maxSize()) {
Log.w(TAG, "DictionaryFacilitator for " + key.toString()
+ " has been evicted due to cache size limit."
+ " size: " + size() + ", maxSize: " + maxSize());
}
}
}
}
private final Context mContext; private final Context mContext;
private final HashSet<Locale> mCachedLocales = new HashSet<>();
private final String mDictionaryNamePrefix; private final String mDictionaryNamePrefix;
private final DictionaryFacilitatorLruCacheInner mLruCache;
private final Object mLock = new Object(); private final Object mLock = new Object();
private final DictionaryFacilitator mDictionaryFacilitator;
private boolean mUseContactsDictionary = false; private boolean mUseContactsDictionary = false;
private Locale mLocale;
public DictionaryFacilitatorLruCache(final Context context, final String dictionaryNamePrefix) { public DictionaryFacilitatorLruCache(final Context context, final String dictionaryNamePrefix) {
mContext = context; mContext = context;
mLruCache = new DictionaryFacilitatorLruCacheInner(
mCachedLocales, MAX_DICTIONARY_FACILITATOR_COUNT);
mDictionaryNamePrefix = dictionaryNamePrefix; mDictionaryNamePrefix = dictionaryNamePrefix;
mDictionaryFacilitator = DictionaryFacilitatorProvider.getDictionaryFacilitator();
} }
private static void waitForLoadingMainDictionary( private static void waitForLoadingMainDictionary(
...@@ -101,59 +63,40 @@ public class DictionaryFacilitatorLruCache { ...@@ -101,59 +63,40 @@ public class DictionaryFacilitatorLruCache {
} }
} }
private void resetDictionariesForLocaleLocked(final DictionaryFacilitator dictionaryFacilitator, private void resetDictionariesForLocaleLocked() {
final Locale locale) {
// Note: Given that personalized dictionaries are not used here; we can pass null account. // Note: Given that personalized dictionaries are not used here; we can pass null account.
dictionaryFacilitator.resetDictionaries(mContext, new Locale[]{locale}, mDictionaryFacilitator.resetDictionaries(mContext, new Locale[]{mLocale},
mUseContactsDictionary, false /* usePersonalizedDicts */, mUseContactsDictionary, false /* usePersonalizedDicts */,
false /* forceReloadMainDictionary */, null /* account */, false /* forceReloadMainDictionary */, null /* account */,
mDictionaryNamePrefix, null /* listener */); mDictionaryNamePrefix, null /* listener */);
} }
public void setUseContactsDictionary(final boolean useContectsDictionary) { public void setUseContactsDictionary(final boolean useContectsDictionary) {
if (mUseContactsDictionary == useContectsDictionary) {
// The value has not been changed.
return;
}
synchronized (mLock) { synchronized (mLock) {
mUseContactsDictionary = useContectsDictionary; if (mUseContactsDictionary == useContectsDictionary) {
for (final Locale locale : mCachedLocales) { // The value has not been changed.
final DictionaryFacilitator dictionaryFacilitator = mLruCache.get(locale); return;
resetDictionariesForLocaleLocked(dictionaryFacilitator, locale);
waitForLoadingMainDictionary(dictionaryFacilitator);
} }
mUseContactsDictionary = useContectsDictionary;
resetDictionariesForLocaleLocked();
waitForLoadingMainDictionary(mDictionaryFacilitator);
} }
} }
public DictionaryFacilitator get(final Locale locale) { public DictionaryFacilitator get(final Locale locale) {
DictionaryFacilitator dictionaryFacilitator = mLruCache.get(locale);
if (dictionaryFacilitator != null) {
// dictionary facilitator for the locale is in the cache.
return dictionaryFacilitator;
}
synchronized (mLock) { synchronized (mLock) {
dictionaryFacilitator = mLruCache.get(locale); if (!mDictionaryFacilitator.isForLocales(new Locale[]{locale})) {
if (dictionaryFacilitator != null) { mLocale = locale;
return dictionaryFacilitator; resetDictionariesForLocaleLocked();
} }
dictionaryFacilitator = DictionaryFacilitatorProvider.getDictionaryFacilitator(); waitForLoadingMainDictionary(mDictionaryFacilitator);
resetDictionariesForLocaleLocked(dictionaryFacilitator, locale); return mDictionaryFacilitator;
waitForLoadingMainDictionary(dictionaryFacilitator);
mLruCache.put(locale, dictionaryFacilitator);
mCachedLocales.add(locale);
return dictionaryFacilitator;
} }
} }
public void evictAll() { public void closeDictionaries() {
synchronized (mLock) { synchronized (mLock) {
mLruCache.evictAll(); mDictionaryFacilitator.closeDictionaries();
mCachedLocales.clear();
} }
} }
@UsedForTesting
HashSet<Locale> getCachedLocalesForTesting() {
return mCachedLocales;
}
} }
...@@ -140,8 +140,8 @@ public final class AndroidSpellCheckerService extends SpellCheckerService ...@@ -140,8 +140,8 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
@Override @Override
public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
if (!PREF_USE_CONTACTS_KEY.equals(key)) return; if (!PREF_USE_CONTACTS_KEY.equals(key)) return;
final boolean useContactsDictionary = prefs.getBoolean(PREF_USE_CONTACTS_KEY, true); final boolean useContactsDictionary = prefs.getBoolean(PREF_USE_CONTACTS_KEY, true);
mDictionaryFacilitatorCache.setUseContactsDictionary(useContactsDictionary); mDictionaryFacilitatorCache.setUseContactsDictionary(useContactsDictionary);
} }
@Override @Override
...@@ -226,7 +226,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService ...@@ -226,7 +226,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
public boolean onUnbind(final Intent intent) { public boolean onUnbind(final Intent intent) {
mSemaphore.acquireUninterruptibly(MAX_NUM_OF_THREADS_READ_DICTIONARY); mSemaphore.acquireUninterruptibly(MAX_NUM_OF_THREADS_READ_DICTIONARY);
try { try {
mDictionaryFacilitatorCache.evictAll(); mDictionaryFacilitatorCache.closeDictionaries();
} finally { } finally {
mSemaphore.release(MAX_NUM_OF_THREADS_READ_DICTIONARY); mSemaphore.release(MAX_NUM_OF_THREADS_READ_DICTIONARY);
} }
......
...@@ -23,21 +23,6 @@ import android.test.suitebuilder.annotation.LargeTest; ...@@ -23,21 +23,6 @@ import android.test.suitebuilder.annotation.LargeTest;
@LargeTest @LargeTest
public class DictionaryFacilitatorLruCacheTests extends AndroidTestCase { public class DictionaryFacilitatorLruCacheTests extends AndroidTestCase {
public void testCacheSize() {
final DictionaryFacilitatorLruCache cache =
new DictionaryFacilitatorLruCache(getContext(), "");
assertEquals(0, cache.getCachedLocalesForTesting().size());
assertNotNull(cache.get(Locale.US));
assertEquals(1, cache.getCachedLocalesForTesting().size());
assertNotNull(cache.get(Locale.UK));
assertEquals(2, cache.getCachedLocalesForTesting().size());
assertNotNull(cache.get(Locale.FRENCH));
assertEquals(2, cache.getCachedLocalesForTesting().size());
cache.evictAll();
assertEquals(0, cache.getCachedLocalesForTesting().size());
}
public void testGetFacilitator() { public void testGetFacilitator() {
final DictionaryFacilitatorLruCache cache = final DictionaryFacilitatorLruCache cache =
new DictionaryFacilitatorLruCache(getContext(), ""); new DictionaryFacilitatorLruCache(getContext(), "");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment