android輸入法機制包含三部分:1,輸入法服務(InputMethodService),簡稱IMS;2,輸入法系統服務(InputMethodManagerService),簡稱IMMS;3,客戶端app(即當前要輸入內容的app);
在分析的時候我先把一些類或介面先列出來
IMS一端
類的關係
我先把類列出來
- InputMethodService;
- IInputMethodWrapper;
- InputMethod <
|– AbstractInputMethodImpl <
|– InputMethodImpl; - InputConnectionWrapper(它實現了InputConnection介面);
- InputContextCallback;
這些類的關係是什麼呢,於是根據程式碼畫了一張UML圖
概括說,service通過onBind()返回一個繼承了Stub的IInputMethodWrapper物件,InputMethodWrapper內部弱引用了一個InputMethodImpl物件。那麼InputConnectionWrapper物件是如何被最終傳遞給service的呢。於是我畫了一個時序圖,如下。
遠端IPC呼叫IInputMethodWrapper的startInput方法,把IInputContext引用的物件傳遞過來,通過時序圖可以看到InputMethodService是如何得到InputConnectionWrapper物件的,從而間接地可以得到IInputContext引用的物件(InputConnectionWrapper內聚了IInputContext)。這就賦予了servie遠端和第三方app客戶端通訊的能力。這個IInputContext提供了什麼介面,service就可以和客戶端做什麼通訊。比如它有個void commitText(CharSequence text, int newCursorPosition);
介面,可以使得service提交文字到客戶端相應的EditText中。
注意,這裡的IInputMethodWrapper是繼承了IInputMethod.Stub,所以它 is-a Binder,實現了aidl定義的介面IInputMethod,而不是InputMethod。 這個容易迷惑人,InputMethod不是aidl定義的。
客戶端
- IInputConnectionWrapper;
- ControlledInputConnectionWrapper;
IInputConnectionWrapper相關的類的關係如下
在客戶端的InputMethodManager的startInputInner方法中,建立了ControlledInputConnectionWrapper物件,並把它作為引數呼叫IInputMethodManager的startInputOrWindowGainedFocus。IInputMethodManager正是IMMS對應的binder,這樣就通過IMMS把ControlledInputConnectionWrapper對應的binder傳遞給了IMS端。
不難想象,這裡的ControlledInputConnectionWrapper所對應的service端的正是InputConnectionWrapper裡邊的IInputContext。
系統服務端
InputMethodManagerService
IMS端和客戶端共用:InputConnection
需要用到的aidl
- IInputContextCallback.aidl
- IInputContext.aidl
- InputBinding.aidl
- IInputMethod.aidl
- IInputMethodManager.aidl
- IInputMethodClient.aidl