1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.inputmethod.pinyin; 18 19 import com.android.inputmethod.pinyin.IPinyinDecoderService; 20 21 import java.io.FileDescriptor; 22 import java.io.FileNotFoundException; 23 import java.io.IOException; 24 import java.util.List; 25 import java.util.Vector; 26 27 import android.app.Service; 28 import android.content.Intent; 29 import android.content.res.AssetFileDescriptor; 30 import android.os.IBinder; 31 import android.os.RemoteException; 32 import android.util.Log; 33 34 /** 35 * This class is used to separate the input method kernel in an individual 36 * service so that both IME and IME-syncer can use it. 37 */ 38 public class PinyinDecoderService extends Service { 39 native static boolean nativeImOpenDecoder(byte fn_sys_dict[], 40 byte fn_usr_dict[]); 41 42 native static boolean nativeImOpenDecoderFd(FileDescriptor fd, 43 long startOffset, long length, byte fn_usr_dict[]); 44 45 native static void nativeImSetMaxLens(int maxSpsLen, int maxHzsLen); 46 47 native static boolean nativeImCloseDecoder(); 48 49 native static int nativeImSearch(byte pyBuf[], int pyLen); 50 51 native static int nativeImDelSearch(int pos, boolean is_pos_in_splid, 52 boolean clear_fixed_this_step); 53 54 native static void nativeImResetSearch(); 55 56 native static int nativeImAddLetter(byte ch); 57 58 native static String nativeImGetPyStr(boolean decoded); 59 60 native static int nativeImGetPyStrLen(boolean decoded); 61 62 native static int[] nativeImGetSplStart(); 63 64 native static String nativeImGetChoice(int choiceId); 65 66 native static int nativeImChoose(int choiceId); 67 68 native static int nativeImCancelLastChoice(); 69 70 native static int nativeImGetFixedLen(); 71 72 native static boolean nativeImCancelInput(); 73 74 native static boolean nativeImFlushCache(); 75 76 native static int nativeImGetPredictsNum(String fixedStr); 77 78 native static String nativeImGetPredictItem(int predictNo); 79 80 // Sync related 81 native static String nativeSyncUserDict(byte[] user_dict, String tomerge); 82 83 native static boolean nativeSyncBegin(byte[] user_dict); 84 85 native static boolean nativeSyncFinish(); 86 87 native static String nativeSyncGetLemmas(); 88 89 native static int nativeSyncPutLemmas(String tomerge); 90 91 native static int nativeSyncGetLastCount(); 92 93 native static int nativeSyncGetTotalCount(); 94 95 native static boolean nativeSyncClearLastGot(); 96 97 native static int nativeSyncGetCapacity(); 98 99 private final static int MAX_PATH_FILE_LENGTH = 100; 100 private static boolean inited = false; 101 102 private String mUsr_dict_file; 103 104 static { 105 try { 106 System.loadLibrary("jni_pinyinime"); 107 } catch (UnsatisfiedLinkError ule) { 108 Log.e("PinyinDecoderService", 109 "WARNING: Could not load jni_pinyinime natives"); 110 } 111 } 112 113 // Get file name of the specified dictionary 114 private boolean getUsrDictFileName(byte usr_dict[]) { 115 if (null == usr_dict) { 116 return false; 117 } 118 119 for (int i = 0; i < mUsr_dict_file.length(); i++) 120 usr_dict[i] = (byte) mUsr_dict_file.charAt(i); 121 usr_dict[mUsr_dict_file.length()] = 0; 122 123 return true; 124 } 125 126 private void initPinyinEngine() { 127 byte usr_dict[]; 128 usr_dict = new byte[MAX_PATH_FILE_LENGTH]; 129 130 // Here is how we open a built-in dictionary for access through 131 // a file descriptor... 132 AssetFileDescriptor afd = getResources().openRawResourceFd( 133 R.raw.dict_pinyin); 134 if (Environment.getInstance().needDebug()) { 135 Log 136 .i("foo", "Dict: start=" + afd.getStartOffset() 137 + ", length=" + afd.getLength() + ", fd=" 138 + afd.getParcelFileDescriptor()); 139 } 140 if (getUsrDictFileName(usr_dict)) { 141 inited = nativeImOpenDecoderFd(afd.getFileDescriptor(), afd 142 .getStartOffset(), afd.getLength(), usr_dict); 143 } 144 try { 145 afd.close(); 146 } catch (IOException e) { 147 } 148 } 149 150 @Override 151 public void onCreate() { 152 super.onCreate(); 153 mUsr_dict_file = getFileStreamPath("usr_dict.dat").getPath(); 154 // This is a hack to make sure our "files" directory has been 155 // created. 156 try { 157 openFileOutput("dummy", 0).close(); 158 } catch (FileNotFoundException e) { 159 } catch (IOException e) { 160 } 161 162 initPinyinEngine(); 163 } 164 165 @Override 166 public void onDestroy() { 167 nativeImCloseDecoder(); 168 inited = false; 169 super.onDestroy(); 170 } 171 172 private final IPinyinDecoderService.Stub mBinder = new IPinyinDecoderService.Stub() { 173 public int getInt() { 174 return 12345; 175 } 176 177 public void setMaxLens(int maxSpsLen, int maxHzsLen) { 178 nativeImSetMaxLens(maxSpsLen, maxHzsLen); 179 } 180 181 public int imSearch(byte[] pyBuf, int pyLen) { 182 return nativeImSearch(pyBuf, pyLen); 183 } 184 185 public int imDelSearch(int pos, boolean is_pos_in_splid, 186 boolean clear_fixed_this_step) { 187 return nativeImDelSearch(pos, is_pos_in_splid, 188 clear_fixed_this_step); 189 } 190 191 public void imResetSearch() { 192 nativeImResetSearch(); 193 } 194 195 public int imAddLetter(byte ch) { 196 return nativeImAddLetter(ch); 197 } 198 199 public String imGetPyStr(boolean decoded) { 200 return nativeImGetPyStr(decoded); 201 } 202 203 public int imGetPyStrLen(boolean decoded) { 204 return nativeImGetPyStrLen(decoded); 205 } 206 207 public int[] imGetSplStart() { 208 return nativeImGetSplStart(); 209 } 210 211 public String imGetChoice(int choiceId) { 212 return nativeImGetChoice(choiceId); 213 } 214 215 public String imGetChoices(int choicesNum) { 216 String retStr = null; 217 for (int i = 0; i < choicesNum; i++) { 218 if (null == retStr) 219 retStr = nativeImGetChoice(i); 220 else 221 retStr += " " + nativeImGetChoice(i); 222 } 223 return retStr; 224 } 225 226 public List<String> imGetChoiceList(int choicesStart, int choicesNum, 227 int sentFixedLen) { 228 Vector<String> choiceList = new Vector<String>(); 229 for (int i = choicesStart; i < choicesStart + choicesNum; i++) { 230 String retStr = nativeImGetChoice(i); 231 if (0 == i) retStr = retStr.substring(sentFixedLen); 232 choiceList.add(retStr); 233 } 234 return choiceList; 235 } 236 237 public int imChoose(int choiceId) { 238 return nativeImChoose(choiceId); 239 } 240 241 public int imCancelLastChoice() { 242 return nativeImCancelLastChoice(); 243 } 244 245 public int imGetFixedLen() { 246 return nativeImGetFixedLen(); 247 } 248 249 public boolean imCancelInput() { 250 return nativeImCancelInput(); 251 } 252 253 public void imFlushCache() { 254 nativeImFlushCache(); 255 } 256 257 public int imGetPredictsNum(String fixedStr) { 258 return nativeImGetPredictsNum(fixedStr); 259 } 260 261 public String imGetPredictItem(int predictNo) { 262 return nativeImGetPredictItem(predictNo); 263 } 264 265 public List<String> imGetPredictList(int predictsStart, int predictsNum) { 266 Vector<String> predictList = new Vector<String>(); 267 for (int i = predictsStart; i < predictsStart + predictsNum; i++) { 268 predictList.add(nativeImGetPredictItem(i)); 269 } 270 return predictList; 271 } 272 273 public String syncUserDict(String tomerge) { 274 byte usr_dict[]; 275 usr_dict = new byte[MAX_PATH_FILE_LENGTH]; 276 277 if (getUsrDictFileName(usr_dict)) { 278 return nativeSyncUserDict(usr_dict, tomerge); 279 } 280 return null; 281 } 282 283 public boolean syncBegin() { 284 byte usr_dict[]; 285 usr_dict = new byte[MAX_PATH_FILE_LENGTH]; 286 287 if (getUsrDictFileName(usr_dict)) { 288 return nativeSyncBegin(usr_dict); 289 } 290 return false; 291 } 292 293 public void syncFinish() { 294 nativeSyncFinish(); 295 } 296 297 public int syncPutLemmas(String tomerge) { 298 return nativeSyncPutLemmas(tomerge); 299 } 300 301 public String syncGetLemmas() { 302 return nativeSyncGetLemmas(); 303 } 304 305 public int syncGetLastCount() { 306 return nativeSyncGetLastCount(); 307 } 308 309 public int syncGetTotalCount() { 310 return nativeSyncGetTotalCount(); 311 } 312 313 public void syncClearLastGot() { 314 nativeSyncClearLastGot(); 315 } 316 317 public int imSyncGetCapacity() { 318 return nativeSyncGetCapacity(); 319 } 320 }; 321 322 @Override 323 public IBinder onBind(Intent intent) { 324 return mBinder; 325 } 326 } 327