Loading java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java +18 −75 Original line number Diff line number Diff line Loading @@ -16,15 +16,11 @@ package com.android.inputmethod.latin; import java.util.HashSet; import java.util.Locale; import java.util.concurrent.TimeUnit; import com.android.inputmethod.annotations.UsedForTesting; import android.content.Context; import android.util.Log; import android.util.LruCache; /** * Cache for dictionary facilitators of multiple locales. Loading @@ -32,54 +28,20 @@ import android.util.LruCache; */ public class 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 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 HashSet<Locale> mCachedLocales = new HashSet<>(); private final String mDictionaryNamePrefix; private final DictionaryFacilitatorLruCacheInner mLruCache; private final Object mLock = new Object(); private final DictionaryFacilitator mDictionaryFacilitator; private boolean mUseContactsDictionary = false; private Locale mLocale; public DictionaryFacilitatorLruCache(final Context context, final String dictionaryNamePrefix) { mContext = context; mLruCache = new DictionaryFacilitatorLruCacheInner( mCachedLocales, MAX_DICTIONARY_FACILITATOR_COUNT); mDictionaryNamePrefix = dictionaryNamePrefix; mDictionaryFacilitator = DictionaryFacilitatorProvider.getDictionaryFacilitator(); } private static void waitForLoadingMainDictionary( Loading @@ -101,59 +63,40 @@ public class DictionaryFacilitatorLruCache { } } private void resetDictionariesForLocaleLocked(final DictionaryFacilitator dictionaryFacilitator, final Locale locale) { private void resetDictionariesForLocaleLocked() { // 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 */, false /* forceReloadMainDictionary */, null /* account */, mDictionaryNamePrefix, null /* listener */); } public void setUseContactsDictionary(final boolean useContectsDictionary) { synchronized (mLock) { if (mUseContactsDictionary == useContectsDictionary) { // The value has not been changed. return; } synchronized (mLock) { mUseContactsDictionary = useContectsDictionary; for (final Locale locale : mCachedLocales) { final DictionaryFacilitator dictionaryFacilitator = mLruCache.get(locale); resetDictionariesForLocaleLocked(dictionaryFacilitator, locale); waitForLoadingMainDictionary(dictionaryFacilitator); } resetDictionariesForLocaleLocked(); waitForLoadingMainDictionary(mDictionaryFacilitator); } } 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) { dictionaryFacilitator = mLruCache.get(locale); if (dictionaryFacilitator != null) { return dictionaryFacilitator; if (!mDictionaryFacilitator.isForLocales(new Locale[]{locale})) { mLocale = locale; resetDictionariesForLocaleLocked(); } dictionaryFacilitator = DictionaryFacilitatorProvider.getDictionaryFacilitator(); resetDictionariesForLocaleLocked(dictionaryFacilitator, locale); waitForLoadingMainDictionary(dictionaryFacilitator); mLruCache.put(locale, dictionaryFacilitator); mCachedLocales.add(locale); return dictionaryFacilitator; waitForLoadingMainDictionary(mDictionaryFacilitator); return mDictionaryFacilitator; } } public void evictAll() { public void closeDictionaries() { synchronized (mLock) { mLruCache.evictAll(); mCachedLocales.clear(); mDictionaryFacilitator.closeDictionaries(); } } @UsedForTesting HashSet<Locale> getCachedLocalesForTesting() { return mCachedLocales; } } java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +3 −3 Original line number Diff line number Diff line Loading @@ -226,7 +226,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService public boolean onUnbind(final Intent intent) { mSemaphore.acquireUninterruptibly(MAX_NUM_OF_THREADS_READ_DICTIONARY); try { mDictionaryFacilitatorCache.evictAll(); mDictionaryFacilitatorCache.closeDictionaries(); } finally { mSemaphore.release(MAX_NUM_OF_THREADS_READ_DICTIONARY); } Loading tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java +0 −15 Original line number Diff line number Diff line Loading @@ -23,21 +23,6 @@ import android.test.suitebuilder.annotation.LargeTest; @LargeTest 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() { final DictionaryFacilitatorLruCache cache = new DictionaryFacilitatorLruCache(getContext(), ""); Loading Loading
java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java +18 −75 Original line number Diff line number Diff line Loading @@ -16,15 +16,11 @@ package com.android.inputmethod.latin; import java.util.HashSet; import java.util.Locale; import java.util.concurrent.TimeUnit; import com.android.inputmethod.annotations.UsedForTesting; import android.content.Context; import android.util.Log; import android.util.LruCache; /** * Cache for dictionary facilitators of multiple locales. Loading @@ -32,54 +28,20 @@ import android.util.LruCache; */ public class 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 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 HashSet<Locale> mCachedLocales = new HashSet<>(); private final String mDictionaryNamePrefix; private final DictionaryFacilitatorLruCacheInner mLruCache; private final Object mLock = new Object(); private final DictionaryFacilitator mDictionaryFacilitator; private boolean mUseContactsDictionary = false; private Locale mLocale; public DictionaryFacilitatorLruCache(final Context context, final String dictionaryNamePrefix) { mContext = context; mLruCache = new DictionaryFacilitatorLruCacheInner( mCachedLocales, MAX_DICTIONARY_FACILITATOR_COUNT); mDictionaryNamePrefix = dictionaryNamePrefix; mDictionaryFacilitator = DictionaryFacilitatorProvider.getDictionaryFacilitator(); } private static void waitForLoadingMainDictionary( Loading @@ -101,59 +63,40 @@ public class DictionaryFacilitatorLruCache { } } private void resetDictionariesForLocaleLocked(final DictionaryFacilitator dictionaryFacilitator, final Locale locale) { private void resetDictionariesForLocaleLocked() { // 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 */, false /* forceReloadMainDictionary */, null /* account */, mDictionaryNamePrefix, null /* listener */); } public void setUseContactsDictionary(final boolean useContectsDictionary) { synchronized (mLock) { if (mUseContactsDictionary == useContectsDictionary) { // The value has not been changed. return; } synchronized (mLock) { mUseContactsDictionary = useContectsDictionary; for (final Locale locale : mCachedLocales) { final DictionaryFacilitator dictionaryFacilitator = mLruCache.get(locale); resetDictionariesForLocaleLocked(dictionaryFacilitator, locale); waitForLoadingMainDictionary(dictionaryFacilitator); } resetDictionariesForLocaleLocked(); waitForLoadingMainDictionary(mDictionaryFacilitator); } } 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) { dictionaryFacilitator = mLruCache.get(locale); if (dictionaryFacilitator != null) { return dictionaryFacilitator; if (!mDictionaryFacilitator.isForLocales(new Locale[]{locale})) { mLocale = locale; resetDictionariesForLocaleLocked(); } dictionaryFacilitator = DictionaryFacilitatorProvider.getDictionaryFacilitator(); resetDictionariesForLocaleLocked(dictionaryFacilitator, locale); waitForLoadingMainDictionary(dictionaryFacilitator); mLruCache.put(locale, dictionaryFacilitator); mCachedLocales.add(locale); return dictionaryFacilitator; waitForLoadingMainDictionary(mDictionaryFacilitator); return mDictionaryFacilitator; } } public void evictAll() { public void closeDictionaries() { synchronized (mLock) { mLruCache.evictAll(); mCachedLocales.clear(); mDictionaryFacilitator.closeDictionaries(); } } @UsedForTesting HashSet<Locale> getCachedLocalesForTesting() { return mCachedLocales; } }
java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +3 −3 Original line number Diff line number Diff line Loading @@ -226,7 +226,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService public boolean onUnbind(final Intent intent) { mSemaphore.acquireUninterruptibly(MAX_NUM_OF_THREADS_READ_DICTIONARY); try { mDictionaryFacilitatorCache.evictAll(); mDictionaryFacilitatorCache.closeDictionaries(); } finally { mSemaphore.release(MAX_NUM_OF_THREADS_READ_DICTIONARY); } Loading
tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java +0 −15 Original line number Diff line number Diff line Loading @@ -23,21 +23,6 @@ import android.test.suitebuilder.annotation.LargeTest; @LargeTest 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() { final DictionaryFacilitatorLruCache cache = new DictionaryFacilitatorLruCache(getContext(), ""); Loading