From f36a97ab3abf7fb3766ed6ff553a2b6501d0908f Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Wed, 2 Oct 2013 18:06:08 +0900 Subject: [PATCH] Try decaying user history at hourly intervals. Bug: 6669677 Change-Id: Ib465fa7e1a7f289a07843535ba89d0dd5259e803 --- java/AndroidManifest.xml | 6 ++ .../latin/ExpandableBinaryDictionary.java | 10 +-- .../android/inputmethod/latin/LatinIME.java | 3 + ...ecayingExpandableBinaryDictionaryBase.java | 4 ++ .../DictionaryDecayBroadcastReciever.java | 66 +++++++++++++++++++ .../PersonalizationHelper.java | 13 +++- 6 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml index b54406f4b..031d62e0c 100644 --- a/java/AndroidManifest.xml +++ b/java/AndroidManifest.xml @@ -110,6 +110,12 @@ + + + + + + diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index 306c1a253..0985aae58 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -273,9 +273,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { lastModifiedTime); } - private void runGCIfRequired() { + protected void runGCIfRequired(final boolean mindsBlockByGC) { if (!ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) return; - if (mBinaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) { + if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) { if (setIsRegeneratingIfNotRegenerating()) { getExecutor(mFilename).execute(new Runnable() { @Override @@ -300,7 +300,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { Log.w(TAG, "addWordDynamically is called for non-updatable dictionary: " + mFilename); return; } - runGCIfRequired(); + runGCIfRequired(true /* mindsBlockByGC */); getExecutor(mFilename).execute(new Runnable() { @Override public void run() { @@ -324,7 +324,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { + mFilename); return; } - runGCIfRequired(); + runGCIfRequired(true /* mindsBlockByGC */); getExecutor(mFilename).execute(new Runnable() { @Override public void run() { @@ -348,7 +348,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { + mFilename); return; } - runGCIfRequired(); + runGCIfRequired(true /* mindsBlockByGC */); getExecutor(mFilename).execute(new Runnable() { @Override public void run() { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 96e16de0d..5b7e9351a 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -77,6 +77,7 @@ import com.android.inputmethod.keyboard.MainKeyboardView; import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.define.ProductionFlag; +import com.android.inputmethod.latin.personalization.DictionaryDecayBroadcastReciever; import com.android.inputmethod.latin.personalization.PersonalizationDictionary; import com.android.inputmethod.latin.personalization.PersonalizationDictionarySessionRegister; import com.android.inputmethod.latin.personalization.PersonalizationHelper; @@ -567,6 +568,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen newDictFilter.addAction(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION); registerReceiver(mDictionaryPackInstallReceiver, newDictFilter); + DictionaryDecayBroadcastReciever.setUpIntervalAlarmForDictionaryDecaying(this); + mInputUpdater = new InputUpdater(this); } diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java index 7cf4f0c88..266216410 100644 --- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java +++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java @@ -236,4 +236,8 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB // Then flush the cleared state of the dictionary on disk. asyncFlashAllBinaryDictionary(); } + + /* package */ void decayIfNeeded() { + runGCIfRequired(false /* mindsBlockByGC */); + } } diff --git a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java new file mode 100644 index 000000000..e9ca662e7 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2013 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.personalization; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import java.util.concurrent.TimeUnit; + +/** + * Broadcast receiver for periodically updating decaying dictionaries. + */ +public class DictionaryDecayBroadcastReciever extends BroadcastReceiver { + /** + * The root domain for the personalization. + */ + private static final String PERSONALIZATION_DOMAIN = + "com.android.inputmethod.latin.personalization"; + + /** + * The action of the intent to tell the time to decay dictionaries. + */ + private static final String DICTIONARY_DECAY_INTENT_ACTION = + PERSONALIZATION_DOMAIN + ".DICT_DECAY"; + + /** + * Interval to update for decaying dictionaries. + */ + private static final long DICTIONARY_DECAY_INTERVAL = TimeUnit.MINUTES.toMillis(60); + + public static void setUpIntervalAlarmForDictionaryDecaying(Context context) { + AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); + final Intent updateIntent = new Intent(DICTIONARY_DECAY_INTENT_ACTION); + updateIntent.setClass(context, DictionaryDecayBroadcastReciever.class); + final long alarmTime = System.currentTimeMillis() + DICTIONARY_DECAY_INTERVAL; + final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0 /* requestCode */, + updateIntent, PendingIntent.FLAG_CANCEL_CURRENT); + if (null != alarmManager) alarmManager.setInexactRepeating(AlarmManager.RTC, + alarmTime, DICTIONARY_DECAY_INTERVAL, pendingIntent); + } + + @Override + public void onReceive(final Context context, final Intent intent) { + final String action = intent.getAction(); + if (action.equals(DICTIONARY_DECAY_INTENT_ACTION)) { + PersonalizationHelper.tryDecayingAllOpeningUserHistoryDictionary(); + } + } +} diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java index 8c9484b12..221ddeeba 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java @@ -29,7 +29,6 @@ import java.util.concurrent.ConcurrentHashMap; public class PersonalizationHelper { private static final String TAG = PersonalizationHelper.class.getSimpleName(); private static final boolean DEBUG = false; - private static final ConcurrentHashMap> sLangUserHistoryDictCache = CollectionUtils.newConcurrentHashMap(); @@ -62,6 +61,18 @@ public class PersonalizationHelper { } } + public static void tryDecayingAllOpeningUserHistoryDictionary() { + for (final ConcurrentHashMap.Entry> entry + : sLangUserHistoryDictCache.entrySet()) { + if (entry.getValue() != null) { + final UserHistoryDictionary dict = entry.getValue().get(); + if (dict != null) { + dict.decayIfNeeded(); + } + } + } + } + public static void registerPersonalizationDictionaryUpdateSession(final Context context, final PersonalizationDictionaryUpdateSession session, String locale) { final PersonalizationPredictionDictionary predictionDictionary =