Added a method and run GC for testing.

Bug: 13231889
Change-Id: If64b7422967c3e4107c845072b64a7bb26a35f7e
main
Keisuke Kuroyanagi 2014-02-28 18:17:09 +09:00
parent d1394b6986
commit d302b98ce6
5 changed files with 40 additions and 14 deletions

View File

@ -28,6 +28,7 @@ import com.android.inputmethod.latin.makedict.FormatSpec;
import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions; import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions;
import com.android.inputmethod.latin.makedict.UnsupportedFormatException; import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import com.android.inputmethod.latin.makedict.WordProperty; import com.android.inputmethod.latin.makedict.WordProperty;
import com.android.inputmethod.latin.personalization.PersonalizationHelper;
import com.android.inputmethod.latin.settings.NativeSuggestOptions; import com.android.inputmethod.latin.settings.NativeSuggestOptions;
import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.FileUtils; import com.android.inputmethod.latin.utils.FileUtils;
@ -508,7 +509,9 @@ public final class BinaryDictionary extends Dictionary {
*/ */
@UsedForTesting @UsedForTesting
public static int setCurrentTimeForTest(final int currentTime) { public static int setCurrentTimeForTest(final int currentTime) {
return setCurrentTimeForTestNative(currentTime); final int currentNativeTimestamp = setCurrentTimeForTestNative(currentTime);
PersonalizationHelper.currentTimeChangedForTesting(currentNativeTimestamp);
return currentNativeTimestamp;
} }
@UsedForTesting @UsedForTesting

View File

@ -163,7 +163,7 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
clearAndFlushDictionary(); clearAndFlushDictionary();
} }
/* package */ void decayIfNeeded() { /* package */ void runGCIfRequired() {
runGCIfRequired(false /* mindsBlockByGC */); runGCIfRequired(false /* mindsBlockByGC */);
} }
} }

View File

@ -43,7 +43,7 @@ public class DictionaryDecayBroadcastReciever extends BroadcastReceiver {
/** /**
* Interval to update for decaying dictionaries. * Interval to update for decaying dictionaries.
*/ */
private static final long DICTIONARY_DECAY_INTERVAL = TimeUnit.MINUTES.toMillis(60); /* package */ static final long DICTIONARY_DECAY_INTERVAL = TimeUnit.MINUTES.toMillis(60);
public static void setUpIntervalAlarmForDictionaryDecaying(Context context) { public static void setUpIntervalAlarmForDictionaryDecaying(Context context) {
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
@ -60,7 +60,7 @@ public class DictionaryDecayBroadcastReciever extends BroadcastReceiver {
public void onReceive(final Context context, final Intent intent) { public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction(); final String action = intent.getAction();
if (action.equals(DICTIONARY_DECAY_INTENT_ACTION)) { if (action.equals(DICTIONARY_DECAY_INTENT_ACTION)) {
PersonalizationHelper.tryDecayingAllOpeningUserHistoryDictionary(); PersonalizationHelper.runGCOnAllOpenedUserHistoryDictionaries();
} }
} }
} }

View File

@ -16,6 +16,7 @@
package com.android.inputmethod.latin.personalization; package com.android.inputmethod.latin.personalization;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.FileUtils; import com.android.inputmethod.latin.utils.FileUtils;
@ -27,6 +28,7 @@ import java.io.FilenameFilter;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class PersonalizationHelper { public class PersonalizationHelper {
private static final String TAG = PersonalizationHelper.class.getSimpleName(); private static final String TAG = PersonalizationHelper.class.getSimpleName();
@ -59,15 +61,36 @@ public class PersonalizationHelper {
} }
} }
public static void tryDecayingAllOpeningUserHistoryDictionary() { private static int sCurrentTimestampForTesting = 0;
for (final ConcurrentHashMap.Entry<String, SoftReference<UserHistoryDictionary>> entry public static void currentTimeChangedForTesting(final int currentTimestamp) {
: sLangUserHistoryDictCache.entrySet()) { if (TimeUnit.MILLISECONDS.toSeconds(
if (entry.getValue() != null) { DictionaryDecayBroadcastReciever.DICTIONARY_DECAY_INTERVAL)
final UserHistoryDictionary dict = entry.getValue().get(); < currentTimestamp - sCurrentTimestampForTesting) {
if (dict != null) { // TODO: Run GC for both PersonalizationDictionary and UserHistoryDictionary.
dict.decayIfNeeded(); runGCOnAllOpenedUserHistoryDictionaries();
} }
} }
public static void runGCOnAllOpenedUserHistoryDictionaries() {
runGCOnAllDictionariesIfRequired(sLangUserHistoryDictCache);
}
@UsedForTesting
public static void runGCOnAllOpenedPersonalizationDictionaries() {
runGCOnAllDictionariesIfRequired(sLangPersonalizationDictCache);
}
private static <T extends DecayingExpandableBinaryDictionaryBase>
void runGCOnAllDictionariesIfRequired(
final ConcurrentHashMap<String, SoftReference<T>> dictionaryMap) {
for (final ConcurrentHashMap.Entry<String, SoftReference<T>> entry
: dictionaryMap.entrySet()) {
final DecayingExpandableBinaryDictionaryBase dict = entry.getValue().get();
if (dict != null) {
dict.runGCIfRequired();
} else {
dictionaryMap.remove(entry.getKey());
}
} }
} }

View File

@ -267,13 +267,13 @@ public class UserHistoryDictionaryTests extends AndroidTestCase {
assertTrue(dict.isInUnderlyingBinaryDictionaryForTests(word)); assertTrue(dict.isInUnderlyingBinaryDictionaryForTests(word));
} }
forcePassingShortTime(); forcePassingShortTime();
dict.decayIfNeeded(); dict.runGCIfRequired();
dict.waitAllTasksForTests(); dict.waitAllTasksForTests();
for (final String word : words) { for (final String word : words) {
assertTrue(dict.isInUnderlyingBinaryDictionaryForTests(word)); assertTrue(dict.isInUnderlyingBinaryDictionaryForTests(word));
} }
forcePassingLongTime(); forcePassingLongTime();
dict.decayIfNeeded(); dict.runGCIfRequired();
dict.waitAllTasksForTests(); dict.waitAllTasksForTests();
for (final String word : words) { for (final String word : words) {
assertFalse(dict.isInUnderlyingBinaryDictionaryForTests(word)); assertFalse(dict.isInUnderlyingBinaryDictionaryForTests(word));