BinaryDictionary.java revision 4250eb27f54f8fedc388fe4825b0646a88778744
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/* 2443c360d0afdbab091994244f045f4756feaf2b4Jean-Baptiste Queru * Copyright (C) 2008 The Android Open Source Project 3e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa * 4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of 6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at 7e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa * 8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa * 10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under 14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License. 15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 17923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpackage com.android.inputmethod.latin; 18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 196f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 208fbd55229243cb66c03d5ea1f79dfb39f596590dsatokimport com.android.inputmethod.keyboard.KeyboardSwitcher; 218fbd55229243cb66c03d5ea1f79dfb39f596590dsatokimport com.android.inputmethod.keyboard.ProximityInfo; 228fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 23fa086c90760bc2bedf0b74eacb0fed3bf7ebc2b7Tadashi G. Takaokaimport android.content.Context; 24fa086c90760bc2bedf0b74eacb0fed3bf7ebc2b7Tadashi G. Takaoka 25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport java.util.Arrays; 26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 27923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Implements a static, compacted, binary dictionary of standard words. 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpublic class BinaryDictionary extends Dictionary { 31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 32cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard public static final String DICTIONARY_PACK_AUTHORITY = 33cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard "com.android.inputmethod.latin.dictionarypack"; 34cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard 35979f8690967ff5409fe18f5085858ccdb8e0ccf1satok /** 36cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard * There is a difference between what java and native code can handle. 37979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * This value should only be used in BinaryDictionary.java 38979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * It is necessary to keep it at this value because some languages e.g. German have 39979f8690967ff5409fe18f5085858ccdb8e0ccf1satok * really long words. 40979f8690967ff5409fe18f5085858ccdb8e0ccf1satok */ 418fbd55229243cb66c03d5ea1f79dfb39f596590dsatok public static final int MAX_WORD_LENGTH = 48; 422e04770adfc16344f69d316efd3ed0a617ede330Tadashi G. Takaoka public static final int MAX_WORDS = 18; 43979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 444250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard @SuppressWarnings("unused") 45979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private static final String TAG = "BinaryDictionary"; 468fbd55229243cb66c03d5ea1f79dfb39f596590dsatok private static final int MAX_PROXIMITY_CHARS_SIZE = ProximityInfo.MAX_PROXIMITY_CHARS_SIZE; 47979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private static final int MAX_BIGRAMS = 60; 48923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 49923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private static final int TYPED_LETTER_MULTIPLIER = 2; 50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 51979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private int mDicTypeId; 52923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private int mNativeDict; 538fbd55229243cb66c03d5ea1f79dfb39f596590dsatok private final int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_PROXIMITY_CHARS_SIZE]; 5430088259480130e5bac5c2028e2c7c3e6d4c51a2satok private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS]; 5530088259480130e5bac5c2028e2c7c3e6d4c51a2satok private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS]; 56e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka private final int[] mScores = new int[MAX_WORDS]; 57e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka private final int[] mBigramScores = new int[MAX_BIGRAMS]; 58923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 598fbd55229243cb66c03d5ea1f79dfb39f596590dsatok private final KeyboardSwitcher mKeyboardSwitcher = KeyboardSwitcher.getInstance(); 60071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka 61071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka public static final Flag FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING = 62c899038eee5c01d520a2707cca01ee093a674d05Jean Chalard new Flag(R.bool.config_require_umlaut_processing, 0x1); 63c899038eee5c01d520a2707cca01ee093a674d05Jean Chalard 64c899038eee5c01d520a2707cca01ee093a674d05Jean Chalard // Can create a new flag from extravalue : 65c899038eee5c01d520a2707cca01ee093a674d05Jean Chalard // public static final Flag FLAG_MYFLAG = 66c899038eee5c01d520a2707cca01ee093a674d05Jean Chalard // new Flag("my_flag", 0x02); 67071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka 68071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka private static final Flag[] ALL_FLAGS = { 69071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka // Here should reside all flags that trigger some special processing 70071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka // These *must* match the definition in UnigramDictionary enum in 71071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka // unigram_dictionary.h so please update both at the same time. 72071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING, 73071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka }; 74071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka 75c2bbc6a4499a6da979381fa0e8e6e855a5ac6aa4Jean Chalard private int mFlags = 0; 76923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 77923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 784250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard * Constructor for the binary dictionary. This is supposed to be called from the 794250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard * dictionary factory. 804250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard * All implementations should pass null into flagArray, except for testing purposes. 814250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard * @param context the context to access the environment from. 824250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard * @param filename the name of the file to read through native code. 834250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard * @param offset the offset of the dictionary data within the file. 844250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard * @param length the length of the binary data. 854250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard * @param flagArray the flags to limit the dictionary to, or null for default. 86923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 874250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard public BinaryDictionary(final Context context, 884250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard final String filename, final long offset, final long length, Flag[] flagArray) { 894250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard // Note: at the moment a binary dictionary is always of the "main" type. 904250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard // Initializing this here will help transitioning out of the scheme where 914250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard // the Suggest class knows everything about every single dictionary. 924250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard mDicTypeId = Suggest.DIC_MAIN; 934250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard // TODO: Stop relying on the state of SubtypeSwitcher, get it as a parameter 944250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard mFlags = Flag.initFlags(null == flagArray ? ALL_FLAGS : flagArray, context, 954250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard SubtypeSwitcher.getInstance()); 964250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard loadDictionary(filename, offset, length); 97979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 98979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 99eaef1c500703b4ee378821884c7b108815ed2983Ken Wakasa static { 100eaef1c500703b4ee378821884c7b108815ed2983Ken Wakasa Utils.loadNativeLibrary(); 101eaef1c500703b4ee378821884c7b108815ed2983Ken Wakasa } 102c2bbc6a4499a6da979381fa0e8e6e855a5ac6aa4Jean Chalard 10390d96615bcb71af7ccbb2318b588aa78c4308e5aKen Wakasa private native int openNative(String sourceDir, long dictOffset, long dictSize, 104e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, 105e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa int maxWords, int maxAlternatives); 106923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private native void closeNative(int dict); 107923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private native boolean isValidWordNative(int nativeData, char[] word, int wordLength); 1088fbd55229243cb66c03d5ea1f79dfb39f596590dsatok private native int getSuggestionsNative(int dict, int proximityInfo, int[] xCoordinates, 109c2bbc6a4499a6da979381fa0e8e6e855a5ac6aa4Jean Chalard int[] yCoordinates, int[] inputCodes, int codesSize, int flags, char[] outputChars, 110e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka int[] scores); 111979f8690967ff5409fe18f5085858ccdb8e0ccf1satok private native int getBigramsNative(int dict, char[] prevWord, int prevWordLength, 112e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores, 113979f8690967ff5409fe18f5085858ccdb8e0ccf1satok int maxWordLength, int maxBigrams, int maxAlternatives); 114979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 11533e0b1e79e464ac48a09433bbfcbb17ded620452Tadashi G. Takaoka private final void loadDictionary(String path, long startOffset, long length) { 11633e0b1e79e464ac48a09433bbfcbb17ded620452Tadashi G. Takaoka mNativeDict = openNative(path, startOffset, length, 117e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka TYPED_LETTER_MULTIPLIER, FULL_WORD_SCORE_MULTIPLIER, 1188fbd55229243cb66c03d5ea1f79dfb39f596590dsatok MAX_WORD_LENGTH, MAX_WORDS, MAX_PROXIMITY_CHARS_SIZE); 119979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 120979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 121979f8690967ff5409fe18f5085858ccdb8e0ccf1satok @Override 122979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public void getBigrams(final WordComposer codes, final CharSequence previousWord, 123887f11ee43ad621aa6ad93d535ab7f48dec73fc7Tadashi G. Takaoka final WordCallback callback) { 124da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa if (mNativeDict == 0) return; 125da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa 126979f8690967ff5409fe18f5085858ccdb8e0ccf1satok char[] chars = previousWord.toString().toCharArray(); 127979f8690967ff5409fe18f5085858ccdb8e0ccf1satok Arrays.fill(mOutputChars_bigrams, (char) 0); 128e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka Arrays.fill(mBigramScores, 0); 129979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 130979f8690967ff5409fe18f5085858ccdb8e0ccf1satok int codesSize = codes.size(); 13189bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard if (codesSize <= 0) { 13289bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Do not return bigrams from BinaryDictionary when nothing was typed. 13389bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard // Only use user-history bigrams (or whatever other bigram dictionaries decide). 13489bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard return; 13589bd776cf68150202d774d62cc1c88664aea5e9fJean Chalard } 136979f8690967ff5409fe18f5085858ccdb8e0ccf1satok Arrays.fill(mInputCodes, -1); 137979f8690967ff5409fe18f5085858ccdb8e0ccf1satok int[] alternatives = codes.getCodesAt(0); 138979f8690967ff5409fe18f5085858ccdb8e0ccf1satok System.arraycopy(alternatives, 0, mInputCodes, 0, 1398fbd55229243cb66c03d5ea1f79dfb39f596590dsatok Math.min(alternatives.length, MAX_PROXIMITY_CHARS_SIZE)); 140979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 141979f8690967ff5409fe18f5085858ccdb8e0ccf1satok int count = getBigramsNative(mNativeDict, chars, chars.length, mInputCodes, codesSize, 142e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS, 1438fbd55229243cb66c03d5ea1f79dfb39f596590dsatok MAX_PROXIMITY_CHARS_SIZE); 144979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 145f5cded1c6cf0f39df13750d4f9f5ba66c1b32964satok for (int j = 0; j < count; ++j) { 146e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka if (mBigramScores[j] < 1) break; 147f5cded1c6cf0f39df13750d4f9f5ba66c1b32964satok final int start = j * MAX_WORD_LENGTH; 148979f8690967ff5409fe18f5085858ccdb8e0ccf1satok int len = 0; 149f5cded1c6cf0f39df13750d4f9f5ba66c1b32964satok while (len < MAX_WORD_LENGTH && mOutputChars_bigrams[start + len] != 0) { 150f5cded1c6cf0f39df13750d4f9f5ba66c1b32964satok ++len; 151979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 152979f8690967ff5409fe18f5085858ccdb8e0ccf1satok if (len > 0) { 153e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka callback.addWord(mOutputChars_bigrams, start, len, mBigramScores[j], 154979f8690967ff5409fe18f5085858ccdb8e0ccf1satok mDicTypeId, DataType.BIGRAM); 155979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 156979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 157923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 158923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 159923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 160887f11ee43ad621aa6ad93d535ab7f48dec73fc7Tadashi G. Takaoka public void getWords(final WordComposer codes, final WordCallback callback) { 1612e04770adfc16344f69d316efd3ed0a617ede330Tadashi G. Takaoka final int count = getSuggestions(codes, mKeyboardSwitcher.getLatinKeyboard(), 162e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka mOutputChars, mScores); 1636f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka 1646f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka for (int j = 0; j < count; ++j) { 165e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka if (mScores[j] < 1) break; 1666f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka final int start = j * MAX_WORD_LENGTH; 1676f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka int len = 0; 1686f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka while (len < MAX_WORD_LENGTH && mOutputChars[start + len] != 0) { 1696f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka ++len; 1706f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka } 1716f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka if (len > 0) { 172e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka callback.addWord(mOutputChars, start, len, mScores[j], mDicTypeId, 1736f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka DataType.UNIGRAM); 1746f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka } 1756f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka } 1766f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka } 1776f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka 1786f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka /* package for test */ boolean isValidDictionary() { 1796f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka return mNativeDict != 0; 1806f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka } 1816f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka 1822e04770adfc16344f69d316efd3ed0a617ede330Tadashi G. Takaoka /* package for test */ int getSuggestions(final WordComposer codes, final Keyboard keyboard, 183e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka char[] outputChars, int[] scores) { 1846f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka if (!isValidDictionary()) return -1; 185da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa 186923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project final int codesSize = codes.size(); 187979f8690967ff5409fe18f5085858ccdb8e0ccf1satok // Won't deal with really long words. 1886f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka if (codesSize > MAX_WORD_LENGTH - 1) return -1; 18930088259480130e5bac5c2028e2c7c3e6d4c51a2satok 190887f11ee43ad621aa6ad93d535ab7f48dec73fc7Tadashi G. Takaoka Arrays.fill(mInputCodes, WordComposer.NOT_A_CODE); 191923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project for (int i = 0; i < codesSize; i++) { 192923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int[] alternatives = codes.getCodesAt(i); 1938fbd55229243cb66c03d5ea1f79dfb39f596590dsatok System.arraycopy(alternatives, 0, mInputCodes, i * MAX_PROXIMITY_CHARS_SIZE, 1948fbd55229243cb66c03d5ea1f79dfb39f596590dsatok Math.min(alternatives.length, MAX_PROXIMITY_CHARS_SIZE)); 195923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1962e04770adfc16344f69d316efd3ed0a617ede330Tadashi G. Takaoka Arrays.fill(outputChars, (char) 0); 197e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka Arrays.fill(scores, 0); 198c3df2d6fd27f3a5b84040b59aece3367769f0cb6Amith Yamasani 1996f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka return getSuggestionsNative( 2006f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka mNativeDict, keyboard.getProximityInfo(), 2018fbd55229243cb66c03d5ea1f79dfb39f596590dsatok codes.getXCoordinates(), codes.getYCoordinates(), mInputCodes, codesSize, 202e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka mFlags, outputChars, scores); 203923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 204923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 205923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 206923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isValidWord(CharSequence word) { 207923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (word == null) return false; 208f590a497393eb77875017010e9a36cf33b095e3cAmith Yamasani char[] chars = word.toString().toCharArray(); 209923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return isValidWordNative(mNativeDict, chars, chars.length); 210923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 211c3df2d6fd27f3a5b84040b59aece3367769f0cb6Amith Yamasani 21236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani @Override 213923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public synchronized void close() { 214da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa closeInternal(); 215da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa } 216da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa 217da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa private void closeInternal() { 218923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (mNativeDict != 0) { 219923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project closeNative(mNativeDict); 220923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mNativeDict = 0; 221923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 222923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 223923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 224923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project @Override 225923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project protected void finalize() throws Throwable { 226da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa try { 227da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa closeInternal(); 228da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa } finally { 229da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa super.finalize(); 230da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa } 231923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 232923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 233