22 展訊Sprd設定-電池-識別輸入法應用
阿新 • • 發佈:2018-11-26
1. 目的
輸入法應用屬於可識別型別且核心應用,不能進行攔截和kill
2. 展訊輸入法判斷
2.1 判斷邏輯塊
//handle inputmethod
if (isLaunchingIMEApp(intent, targetApp, targetUid, callerApp, reason)) {
return true;
}
2.2 判斷是否為輸入法
private boolean isLaunchingIMEApp(Intent intent, String targetApp, int targetUid, String callerApp, String reason) { //handle inputmethod // 是否滿足以下條件 // 1. caller 為系統發起 // 2. 啟動型別為bind-services // 3. action為輸入法型別 if ("android".equals(callerApp) && REASON_BIND_SERVICE.equals(reason) && intent != null && "android.view.InputMethod".equals(intent.getAction())) { // 判斷為輸入法應用 if (targetApp != null) { // a input method // 如果未儲存到當前可用輸入法,則存入mEnabledInputMethodAppList列表中 int index = mEnabledInputMethodAppList.indexOf(targetApp); if (index < 0) { mEnabledInputMethodAppList.add(targetApp); // 多使用者模式下,儲存輸入法資訊到對應列表中 int userId = UserHandle.getUserId(targetUid); mAppStateInfoCollector.updateAppInputMethodState(targetApp, true, userId); mAppStateInfoCollector.setDefaultInputMethodApp(targetApp, userId); } } return true; } // allow to start input Method // 是否滿足下面條件 // 1. 啟動型別為bind-services // 2. caller 為系統發起 // 3. 該程序屬於輸入法列表 if (REASON_BIND_SERVICE.equals(reason) && "android".equals(callerApp) && isInputMethodApp(targetApp)) { if (DEBUG) Slog.d(TAG, "isLaunchingIMEApp: "+targetApp + ", callingPackage = "+callerApp+", reason = "+reason +" allow for input method"); return true; } return false; } // input method app private boolean isInputMethodApp(String pkgName) { int index = mEnabledInputMethodAppList.indexOf(pkgName); if (index >= 0) { return true; } return false; }
2.3 AppStateInfoCollector.updateAppInputMethodState
更新對應程序狀態中,應用狀態mIsEnabledInputMethod為輸入法應用
// update the Input Method identify state of this app public void updateAppInputMethodState(String pkgName, boolean isInputMethod, int userId) { ArrayMap<String, AppState> mAppStateInfoList = getAppStateInfoList(userId); int index = mAppStateInfoList.indexOfKey(pkgName); if (index >= 0) { AppState appState = mAppStateInfoList.valueAt(index); appState.mIsEnabledInputMethod = isInputMethod; } }
2.4 AppStateInfoCollector.setDefaultInputMethodApp
更新為預設輸入法
// update the Input Method identify state of this app public void setDefaultInputMethodApp(String pkgName, int userId) { ArrayMap<String, AppState> mAppStateInfoList = getAppStateInfoList(userId); String mDefaultIMEAppName = mDefaultIMEAppNameForUsers.get(userId); // 新值與預設輸入法一致,則不需要重複更新 if (mDefaultIMEAppName != null && mDefaultIMEAppName.equals(pkgName)) { return; } // 舊的預設輸入法更新狀態 // clear orignal if (mDefaultIMEAppName != null) { int index = mAppStateInfoList.indexOfKey(mDefaultIMEAppName); if (index >= 0) { AppState appState = mAppStateInfoList.valueAt(index); appState.mIsDefaultInputMethod = false; } } // set new // 新值設定為預設輸入法即當前使用的輸入法 int index = mAppStateInfoList.indexOfKey(pkgName); if (index >= 0) { AppState appState = mAppStateInfoList.valueAt(index); appState.mIsDefaultInputMethod = true; } mDefaultIMEAppName = pkgName; mDefaultIMEAppNameForUsers.put(userId, mDefaultIMEAppName); }
2.5 APPstate建立中會進行判斷是否為輸入法
// check if is input method
retVal.mIsEnabledInputMethod = isEnabledIMEApp(packageName);
// if this app is a input Method
private boolean isEnabledIMEApp(String pkgName){
if (pkgName == null) return false;
IInputMethodManager service = IInputMethodManager.Stub.asInterface(
ServiceManager.getService(Context.INPUT_METHOD_SERVICE));
List<InputMethodInfo> inputMethods;
try {
inputMethods = service.getEnabledInputMethodList();
} catch (RemoteException e) {
return false;
}
if (inputMethods == null || inputMethods.size() == 0) return false;
for (InputMethodInfo info : inputMethods){
if (info == null || info.getPackageName() == null) continue;
if (info.getPackageName().equals(pkgName)) return true;
}
return false;
}
3. 應用上層的輸入法判斷
3.1 判斷是否為預設輸入法,或者正在使用的當前輸入法
public static String getInputPackage(Context mContext) {
String result = null;
String input = Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
if (input == null || input.equals("") || !input.contains("/")) {
// frameworks/base/packages/SettingsProvider/res/values/defaults.xml, default_input_method
} else {
result = input.substring(0, input.indexOf('/'));
}
Log.d(TAG, "getInputPackage = " + result);
return result;
}
3.2 根據AndroidManifest進行判斷是否為輸入法
public static boolean isInputMethodApp(Context context, String packageName) {
PackageManager pm = context.getPackageManager();
boolean isInputMethodApp = false;
try {
PackageInfo pkgInfo = pm.getPackageInfo(packageName, PackageManager.GET_SERVICES);
ServiceInfo[] sInfo = pkgInfo.services;
if (sInfo != null) {
for (int i = 0; i < sInfo.length; i++) {
ServiceInfo serviceInfo = sInfo[i];
if (serviceInfo.permission != null && serviceInfo.permission.equals("android.permission.BIND_INPUT_METHOD")) {
isInputMethodApp = true;
break;
}
}
}
} catch (NameNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return isInputMethodApp;
}
3.3 根據 InputMethodManager 進行獲取輸入法列表
public static ArrayList<String> getInputMethodAppList(Context context) {
ArrayList<String> list = new ArrayList<String>();
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
List<InputMethodInfo> methodList = imm.getInputMethodList();
List<String> mInputMethodBlackList = getInputMethodBlackList(context);
if (methodList != null) {
for (InputMethodInfo mi : methodList) {
String inputMethodPackageName = mi.getPackageName();
if (!mInputMethodBlackList.contains(inputMethodPackageName)) {
list.add(inputMethodPackageName);
}
}
}
Log.d(TAG, "getInputMethodAppList = " + list.toString());
return list;
}