/* * Copyright (C) 2009 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.pinyin; import com.android.inputmethod.pinyin.IPinyinDecoderService; import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; import java.util.Vector; import android.app.Service; import android.content.Intent; import android.content.res.AssetFileDescriptor; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; /** * This class is used to separate the input method kernel in an individual * service so that both IME and IME-syncer can use it. */ public class PinyinDecoderService extends Service { native static boolean nativeImOpenDecoder(byte fn_sys_dict[], byte fn_usr_dict[]); native static boolean nativeImOpenDecoderFd(FileDescriptor fd, long startOffset, long length, byte fn_usr_dict[]); native static void nativeImSetMaxLens(int maxSpsLen, int maxHzsLen); native static boolean nativeImCloseDecoder(); native static int nativeImSearch(byte pyBuf[], int pyLen); native static int nativeImDelSearch(int pos, boolean is_pos_in_splid, boolean clear_fixed_this_step); native static void nativeImResetSearch(); native static int nativeImAddLetter(byte ch); native static String nativeImGetPyStr(boolean decoded); native static int nativeImGetPyStrLen(boolean decoded); native static int[] nativeImGetSplStart(); native static String nativeImGetChoice(int choiceId); native static int nativeImChoose(int choiceId); native static int nativeImCancelLastChoice(); native static int nativeImGetFixedLen(); native static boolean nativeImCancelInput(); native static boolean nativeImFlushCache(); native static int nativeImGetPredictsNum(String fixedStr); native static String nativeImGetPredictItem(int predictNo); // Sync related native static String nativeSyncUserDict(byte[] user_dict, String tomerge); native static boolean nativeSyncBegin(byte[] user_dict); native static boolean nativeSyncFinish(); native static String nativeSyncGetLemmas(); native static int nativeSyncPutLemmas(String tomerge); native static int nativeSyncGetLastCount(); native static int nativeSyncGetTotalCount(); native static boolean nativeSyncClearLastGot(); native static int nativeSyncGetCapacity(); private final static int MAX_PATH_FILE_LENGTH = 100; private static boolean inited = false; private String mUsr_dict_file; static { try { System.loadLibrary("jni_pinyinime"); } catch (UnsatisfiedLinkError ule) { Log.e("PinyinDecoderService", "WARNING: Could not load jni_pinyinime natives"); } } // Get file name of the specified dictionary private boolean getUsrDictFileName(byte usr_dict[]) { if (null == usr_dict) { return false; } for (int i = 0; i < mUsr_dict_file.length(); i++) usr_dict[i] = (byte) mUsr_dict_file.charAt(i); usr_dict[mUsr_dict_file.length()] = 0; return true; } private void initPinyinEngine() { byte usr_dict[]; usr_dict = new byte[MAX_PATH_FILE_LENGTH]; // Here is how we open a built-in dictionary for access through // a file descriptor... AssetFileDescriptor afd = getResources().openRawResourceFd( R.raw.dict_pinyin); if (Environment.getInstance().needDebug()) { Log .i("foo", "Dict: start=" + afd.getStartOffset() + ", length=" + afd.getLength() + ", fd=" + afd.getParcelFileDescriptor()); } if (getUsrDictFileName(usr_dict)) { inited = nativeImOpenDecoderFd(afd.getFileDescriptor(), afd .getStartOffset(), afd.getLength(), usr_dict); } try { afd.close(); } catch (IOException e) { } } @Override public void onCreate() { super.onCreate(); mUsr_dict_file = getFileStreamPath("usr_dict.dat").getPath(); // This is a hack to make sure our "files" directory has been // created. try { openFileOutput("dummy", 0).close(); } catch (FileNotFoundException e) { } catch (IOException e) { } initPinyinEngine(); } @Override public void onDestroy() { nativeImCloseDecoder(); inited = false; super.onDestroy(); } private final IPinyinDecoderService.Stub mBinder = new IPinyinDecoderService.Stub() { public int getInt() { return 12345; } public void setMaxLens(int maxSpsLen, int maxHzsLen) { nativeImSetMaxLens(maxSpsLen, maxHzsLen); } public int imSearch(byte[] pyBuf, int pyLen) { return nativeImSearch(pyBuf, pyLen); } public int imDelSearch(int pos, boolean is_pos_in_splid, boolean clear_fixed_this_step) { return nativeImDelSearch(pos, is_pos_in_splid, clear_fixed_this_step); } public void imResetSearch() { nativeImResetSearch(); } public int imAddLetter(byte ch) { return nativeImAddLetter(ch); } public String imGetPyStr(boolean decoded) { return nativeImGetPyStr(decoded); } public int imGetPyStrLen(boolean decoded) { return nativeImGetPyStrLen(decoded); } public int[] imGetSplStart() { return nativeImGetSplStart(); } public String imGetChoice(int choiceId) { return nativeImGetChoice(choiceId); } public String imGetChoices(int choicesNum) { String retStr = null; for (int i = 0; i < choicesNum; i++) { if (null == retStr) retStr = nativeImGetChoice(i); else retStr += " " + nativeImGetChoice(i); } return retStr; } public List imGetChoiceList(int choicesStart, int choicesNum, int sentFixedLen) { Vector choiceList = new Vector(); for (int i = choicesStart; i < choicesStart + choicesNum; i++) { String retStr = nativeImGetChoice(i); if (0 == i) retStr = retStr.substring(sentFixedLen); choiceList.add(retStr); } return choiceList; } public int imChoose(int choiceId) { return nativeImChoose(choiceId); } public int imCancelLastChoice() { return nativeImCancelLastChoice(); } public int imGetFixedLen() { return nativeImGetFixedLen(); } public boolean imCancelInput() { return nativeImCancelInput(); } public void imFlushCache() { nativeImFlushCache(); } public int imGetPredictsNum(String fixedStr) { return nativeImGetPredictsNum(fixedStr); } public String imGetPredictItem(int predictNo) { return nativeImGetPredictItem(predictNo); } public List imGetPredictList(int predictsStart, int predictsNum) { Vector predictList = new Vector(); for (int i = predictsStart; i < predictsStart + predictsNum; i++) { predictList.add(nativeImGetPredictItem(i)); } return predictList; } public String syncUserDict(String tomerge) { byte usr_dict[]; usr_dict = new byte[MAX_PATH_FILE_LENGTH]; if (getUsrDictFileName(usr_dict)) { return nativeSyncUserDict(usr_dict, tomerge); } return null; } public boolean syncBegin() { byte usr_dict[]; usr_dict = new byte[MAX_PATH_FILE_LENGTH]; if (getUsrDictFileName(usr_dict)) { return nativeSyncBegin(usr_dict); } return false; } public void syncFinish() { nativeSyncFinish(); } public int syncPutLemmas(String tomerge) { return nativeSyncPutLemmas(tomerge); } public String syncGetLemmas() { return nativeSyncGetLemmas(); } public int syncGetLastCount() { return nativeSyncGetLastCount(); } public int syncGetTotalCount() { return nativeSyncGetTotalCount(); } public void syncClearLastGot() { nativeSyncClearLastGot(); } public int imSyncGetCapacity() { return nativeSyncGetCapacity(); } }; @Override public IBinder onBind(Intent intent) { return mBinder; } }