187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi/* 287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * Copyright (C) 2013 The Android Open Source Project 387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * 487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * Licensed under the Apache License, Version 2.0 (the "License"); 587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * you may not use this file except in compliance with the License. 687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * You may obtain a copy of the License at 787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * 887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * http://www.apache.org/licenses/LICENSE-2.0 987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * 1087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * Unless required by applicable law or agreed to in writing, software 1187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * distributed under the License is distributed on an "AS IS" BASIS, 1287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * See the License for the specific language governing permissions and 1487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * limitations under the License. 1587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi */ 1687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 1787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagipackage com.android.inputmethod.latin.personalization; 1887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 1987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport android.content.Context; 2087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 21e5a35711b854aedeeea2f45105b941b9deee49bcSatoshi Kataokaimport com.android.inputmethod.annotations.UsedForTesting; 2297485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataokaimport com.android.inputmethod.compat.ActivityManagerCompatUtils; 2387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.keyboard.ProximityInfo; 2487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.AbstractDictionaryWriter; 2587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.ExpandableDictionary; 2687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.WordComposer; 2787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.ExpandableDictionary.NextWord; 2887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; 2987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.makedict.DictEncoder; 3087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.makedict.FormatSpec; 3187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.makedict.UnsupportedFormatException; 3287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.utils.UserHistoryDictIOUtils; 3387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.utils.UserHistoryDictIOUtils.BigramDictionaryInterface; 3487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.utils.UserHistoryForgettingCurveUtils; 3587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport com.android.inputmethod.latin.utils.UserHistoryForgettingCurveUtils.ForgettingCurveParams; 3687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 3787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport java.io.IOException; 3887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagiimport java.util.ArrayList; 395ed30a7660048ef4bf78077e77554c97786eae2bKeisuke Kuroyanagiimport java.util.Map; 4087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 4187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi// Currently this class is used to implement dynamic prodiction dictionary. 4287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi// TODO: Move to native code. 4387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagipublic class DynamicPersonalizationDictionaryWriter extends AbstractDictionaryWriter { 4487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi private static final String TAG = DynamicPersonalizationDictionaryWriter.class.getSimpleName(); 4587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi /** Maximum number of pairs. Pruning will start when databases goes above this number. */ 4697485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka public static final int DEFAULT_MAX_HISTORY_BIGRAMS = 10000; 4797485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka public static final int LOW_MEMORY_MAX_HISTORY_BIGRAMS = 2000; 4887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 4987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi /** Any pair being typed or picked */ 5087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi private static final int FREQUENCY_FOR_TYPED = 2; 5187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 5287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi private static final int BINARY_DICT_VERSION = 3; 5387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi private static final FormatSpec.FormatOptions FORMAT_OPTIONS = 5487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi new FormatSpec.FormatOptions(BINARY_DICT_VERSION, true /* supportsDynamicUpdate */); 5587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 5687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi private final UserHistoryDictionaryBigramList mBigramList = 5787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi new UserHistoryDictionaryBigramList(); 5887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi private final ExpandableDictionary mExpandableDictionary; 5997485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka private final int mMaxHistoryBigrams; 6087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 6187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi public DynamicPersonalizationDictionaryWriter(final Context context, final String dictType) { 6287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi super(context, dictType); 636e04d6593239e841f5dac0d3f32d613967c11e22Keisuke Kuroyanagi mExpandableDictionary = new ExpandableDictionary(dictType); 6497485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka final boolean isLowRamDevice = ActivityManagerCompatUtils.isLowRamDevice(context); 6597485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka mMaxHistoryBigrams = isLowRamDevice ? 6697485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka LOW_MEMORY_MAX_HISTORY_BIGRAMS : DEFAULT_MAX_HISTORY_BIGRAMS; 6787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 6887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 6987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi @Override 7087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi public void clear() { 7187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi mBigramList.evictAll(); 7287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi mExpandableDictionary.clearDictionary(); 7387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 7487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 7587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi /** 7687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * Adds a word unigram to the fusion dictionary. Call updateBinaryDictionary when all changes 7787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi * are done to update the binary dictionary. 78f3204eebb19f0f8fae9d6d81e7e2b430f29829a0Jean Chalard * @param word The word to add. 79f3204eebb19f0f8fae9d6d81e7e2b430f29829a0Jean Chalard * @param shortcutTarget A shortcut target for this word, or null if none. 80f3204eebb19f0f8fae9d6d81e7e2b430f29829a0Jean Chalard * @param frequency The frequency for this unigram. 81f3204eebb19f0f8fae9d6d81e7e2b430f29829a0Jean Chalard * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored 82f3204eebb19f0f8fae9d6d81e7e2b430f29829a0Jean Chalard * if shortcutTarget is null. 83f3204eebb19f0f8fae9d6d81e7e2b430f29829a0Jean Chalard * @param isNotAWord true if this is not a word, i.e. shortcut only. 8487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi */ 8587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi @Override 8687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi public void addUnigramWord(final String word, final String shortcutTarget, final int frequency, 87f3204eebb19f0f8fae9d6d81e7e2b430f29829a0Jean Chalard final int shortcutFreq, final boolean isNotAWord) { 8897485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka if (mBigramList.size() > mMaxHistoryBigrams * 2) { 89a328f538c34ad2dafdfa53642085cb1072224d80Yuichiro Hanada // Too many entries: just stop adding new vocabulary and wait next refresh. 9097485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka return; 9197485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka } 92f3204eebb19f0f8fae9d6d81e7e2b430f29829a0Jean Chalard mExpandableDictionary.addWord(word, shortcutTarget, frequency, shortcutFreq); 9387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi mBigramList.addBigram(null, word, (byte)frequency); 9487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 9587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 9687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi @Override 9787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi public void addBigramWords(final String word0, final String word1, final int frequency, 9887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi final boolean isValid, final long lastModifiedTime) { 9997485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka if (mBigramList.size() > mMaxHistoryBigrams * 2) { 100a328f538c34ad2dafdfa53642085cb1072224d80Yuichiro Hanada // Too many entries: just stop adding new vocabulary and wait next refresh. 10197485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka return; 10297485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka } 10387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi if (lastModifiedTime > 0) { 10487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi mExpandableDictionary.setBigramAndGetFrequency(word0, word1, 10587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi new ForgettingCurveParams(frequency, System.currentTimeMillis(), 10687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi lastModifiedTime)); 10787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi mBigramList.addBigram(word0, word1, (byte)frequency); 10887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } else { 10987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi mExpandableDictionary.setBigramAndGetFrequency(word0, word1, 11087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi new ForgettingCurveParams(isValid)); 11187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi mBigramList.addBigram(word0, word1, (byte)frequency); 11287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 11387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 11487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 11587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi @Override 11687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi public void removeBigramWords(final String word0, final String word1) { 11787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi if (mBigramList.removeBigram(word0, word1)) { 11887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi mExpandableDictionary.removeBigram(word0, word1); 11987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 12087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 12187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 12287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi @Override 1235ed30a7660048ef4bf78077e77554c97786eae2bKeisuke Kuroyanagi protected void writeDictionary(final DictEncoder dictEncoder, 1245ed30a7660048ef4bf78077e77554c97786eae2bKeisuke Kuroyanagi final Map<String, String> attributeMap) throws IOException, UnsupportedFormatException { 12587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi UserHistoryDictIOUtils.writeDictionary(dictEncoder, 12697485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka new FrequencyProvider(mBigramList, mExpandableDictionary, mMaxHistoryBigrams), 12797485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka mBigramList, FORMAT_OPTIONS); 12887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 12987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 13087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi private static class FrequencyProvider implements BigramDictionaryInterface { 13197485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka private final UserHistoryDictionaryBigramList mBigramList; 13297485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka private final ExpandableDictionary mExpandableDictionary; 13397485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka private final int mMaxHistoryBigrams; 13487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 13587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi public FrequencyProvider(final UserHistoryDictionaryBigramList bigramList, 13697485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka final ExpandableDictionary expandableDictionary, final int maxHistoryBigrams) { 13787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi mBigramList = bigramList; 13887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi mExpandableDictionary = expandableDictionary; 13997485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka mMaxHistoryBigrams = maxHistoryBigrams; 14087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 14197485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka 14287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi @Override 14387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi public int getFrequency(final String word0, final String word1) { 14487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi final int freq; 14587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi if (word0 == null) { // unigram 14687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi freq = FREQUENCY_FOR_TYPED; 14787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } else { // bigram 14887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi final NextWord nw = mExpandableDictionary.getBigramWord(word0, word1); 14987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi if (nw != null) { 15087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi final ForgettingCurveParams forgettingCurveParams = nw.getFcParams(); 15187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi final byte prevFc = mBigramList.getBigrams(word0).get(word1); 15287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi final byte fc = forgettingCurveParams.getFc(); 15387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi final boolean isValid = forgettingCurveParams.isValid(); 15487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi if (prevFc > 0 && prevFc == fc) { 15587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi freq = fc & 0xFF; 15687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } else if (UserHistoryForgettingCurveUtils. 15797485273d7c5fdf9b05a7a1c1397cce9721a62d0Satoshi Kataoka needsToSave(fc, isValid, mBigramList.size() <= mMaxHistoryBigrams)) { 15887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi freq = fc & 0xFF; 15987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } else { 16087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi // Delete this entry 16187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi freq = -1; 16287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 16387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } else { 16487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi // Delete this entry 16587a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi freq = -1; 16687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 16787a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 16887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi return freq; 16987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 17087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 17187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 17287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi @Override 17387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, 17487a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi final String prevWord, final ProximityInfo proximityInfo, 175fe87f5f41744a633a2ed91af9b171bda2637649eKeisuke Kuroyanagi boolean blockOffensiveWords, final int[] additionalFeaturesOptions) { 17687a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi return mExpandableDictionary.getSuggestions(composer, prevWord, proximityInfo, 177fe87f5f41744a633a2ed91af9b171bda2637649eKeisuke Kuroyanagi blockOffensiveWords, additionalFeaturesOptions); 17887a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 17987a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi 18087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi @Override 18187a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi public boolean isValidWord(final String word) { 18287a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi return mExpandableDictionary.isValidWord(word); 18387a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi } 184e5a35711b854aedeeea2f45105b941b9deee49bcSatoshi Kataoka 185e5a35711b854aedeeea2f45105b941b9deee49bcSatoshi Kataoka @UsedForTesting 186a328f538c34ad2dafdfa53642085cb1072224d80Yuichiro Hanada public boolean isInBigramListForTests(final String word) { 187e5a35711b854aedeeea2f45105b941b9deee49bcSatoshi Kataoka // TODO: Use native method to determine whether the word is in dictionary or not 188a328f538c34ad2dafdfa53642085cb1072224d80Yuichiro Hanada return mBigramList.containsKey(word) || mBigramList.getBigrams(null).containsKey(word); 189e5a35711b854aedeeea2f45105b941b9deee49bcSatoshi Kataoka } 19087a72f50c23a4ef357ae623eabc2af16d02466aeKeisuke Kuroyanagi} 191