1.1 安卓IME整体框架
IME整体分为三个部分
1.1.1 输入法客户端(IMM)
主要指输入法框架的InputMethodManager,每个app都一个实例,用来和输入法控制端交互。运行在需要使用输入法的进程。
1.1.2 输入法管理端(IMMS)
主要指输入法框架的InputMethodManagerService,运行在system_server进程,工作内容包含以下:
输入法服务端的绑定
输入法服务端与输入法客户端的绑定
输入法启用/关闭
输入法显示/隐藏
切换输入法
1.1.3 输入法服务端(IMS)
主要指输入法框架的InputMethodService,这是一个输入法服务,真正实现输入法界面,控制字符输入的地方。运行在输入法进程,例如搜狗输入法进程。
1.1.4 子模块交互流程图
输入法的整体交互过程如下:
- IMM利用IInputMethodManager请求IMMS
- IMMS绑定输入法服务InputMethodService,得到IInputMethod
- IMMS请求IInputMethod创建交互IIputMethodSession
- IMMS通过IInputMethodClient告知IMM IInputMethodSession
- IMM和IMS通过IIputMethodSession和IIputContext交互
1.2 IME初始化启动流程
1.2.1 IME客户端(IMM)初始化流程
涉及代码文件路径: frameworks/base/core/java/android/view/ViewRootImpl.java
frameworks/base/core/java/android/view/WindowManagerGlobal.java
frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java
frameworks/base/core/java/com/android/internal/view/IInputMethodClient.aidl
frameworks/base/core/java/com/android/internal/view/IInputContext.aidl
frameworks/base/core/java/com/android/internal/view/IInputMethodManager.aidl
frameworks/base/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
IMM子模块运行在需要使用输入法的进程。
IMMS子模块运行在system_server进程。
1.2.2 IME管理端(IMMS)初始化流程
IMMS运行在system server进程中,属于系统服务的一部分,用于控制输入法的显示/隐藏、切换、绑定等操作。
涉及代码文件路径: frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
frameworks/base/core/java/android/os/SystemService.java
frameworks/base/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
frameworks/base/packages/SettingsProvider/res/values/defaults.xml
InputMethodManagerService(IMMS)初始化流程:从SystemService启动service开始
1.2.3 IME服务端(IMS)初始化流程
IMS运行在输入法进程, 是一种特殊的输入法后台服务,继承结构为:InputMethodService extends AbstractInputMethodServiceService 输入法服务本质上是一个服务, 使用时需要IMMS通过bindService的方式绑定。 初始化过程在Service的onCreate方法中, 绑定方法在onBind方法中。
涉及代码文件路径: frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java
frameworks/base/core/java/com/android/internal/view/IInputMethodManager.aidl
frameworks/base/core/java/android/inputmethodservice/InputMethodService.java
packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java
# 从InputMethodManager.java开始
InputMethodManager.java -- startInput
---》 startInputInner
---> IInputMethodManager.aidl -- startInputOrWindowGainedFocus
---> InputMethodManagerService.java -- startInputOrWindowGainedFocus
---》 startInputOrWindowGainedFocusInternal
---》 startInputOrWindowGainedFocusInternalLocked
---》 startInputUncheckedLocked
---》 调用bindCurrentInputMethodServiceLocked,启动当前默认的输入法的服务(启动在设置的输入法进程中)
---》 调用bindServiceAsUser,例如AOSP提供的packages/inputmethods/LatinIME输入法,可以在AndroidManifest.xml看到输入法service,即此处的绑定的服务
# 参考packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java
---》 输入法APP中会调用InputMethodManager的setAdditionalInputMethodSubtypes,然后调用到InputMethodManagerService.java对应函数
---》 调用buildInputMethodListLocked检查当前默认的输入法(LatinIME)服务是否存在
---》 调用setInputMethodEnabledLocked检查默认的LatinIME是否是可用的可用的输入法,如果不可用,则设置为可用(即检查settingprovider数据库的enabled_input_methods信息)
# 输入法应用会继承InputMethodService,比如packages/inputmethods/LatinIME/java/src/com/android/inputmethod/latin/LatinIME.java
# 因此会实现InputMethodService的onCreate函数
# 从onTouchEvent开始,viewClicked流程
1 viewClicked
2 checkFocus
3 startInputInner
4 startInputOrWindowGainedFocus
5 startInputLocked
6 startInputUncheckedLocked
7 attachNewInputLocked
1.3 输入法弹出流程
1.3.1 点击弹出输入法流程
1 viewClicked流程
1.1 viewClicked
1.2 checkFocus
1.3 startInputInner
1.4 startInputOrWindowGainedFocus
1.5 startInputLocked
1.6 startInputUncheckedLocked
1.7 attachNewInputLocked
1.7.1 处理返回的结果
2 showSoftInput流程
2.1 showSoftInput
2.2 IMMS#showSoftInput
2.3 showCurrentInputLocked
2.4 IMS$InputMethodImpl$showSoftInput
2.5 dispatchOnShowInputRequested
2.6 IMS$showWindow
2.7 showWindowInner