Android Input系統原始碼分析一(啟動與初始化)
一. Input系統的啟動
Android Framework是由一系列的Service所構建起來的,其中與Input相關的主要是InputManagerService(IMS)。我們看看IMS的啟動流程。
IMS是在SystemServer.startOtherService中起來的,相應的程式碼如下:
private void startOtherServices() { ... InputManagerService inputManager = null; ... traceBeginAndSlog("StartInputManagerService"); inputManager = new InputManagerService(context); traceEnd(); ... traceBeginAndSlog("StartInputManager"); inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); inputManager.start(); traceEnd();
在startOthervice中,先是會建立一個InputManagerService物件-inputManager,在後面會去呼叫IMS.start來啟動IMS。
我們先來看看IMS的建構函式:
public InputManagerService(Context context) { // 建立Handler物件,使用的是DisplayThread這個執行緒的looper this.mContext = context; this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper()); .... // 走JNI呼叫native層的nativeInit方法進行初始化 mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue()); ... // 將IMS加入LocalService,這樣IMS可以被SystemServer內的其他service使用 LocalServices.addService(InputManagerInternal.class, new LocalService()); }
可知IMS的建構函式自身所做的事情並不多,主要的事情應該是由nativeInit在native層完成的。再來看看nativeInit的實現:
nativeInit中首先根據Java層傳人的訊息佇列object建立native層對應的messageQueue物件,然後建立NativeInputManager物件:
NativeInputManager::NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper) : mLooper(looper), mInteractive(true) { // 利用jniEnv,建立Java側的context、IMS物件在native層對應的object JNIEnv* env = jniEnv(); mContextObj = env->NewGlobalRef(contextObj); mServiceObj = env->NewGlobalRef(serviceObj); // 建立一個EventHub物件,這個很重要,是跟Input驅動層進行互動的物件 sp<EventHub> eventHub = new EventHub(); // 建立一個InputManager物件,也很重要 mInputManager = new InputManager(eventHub, this, this); }
在NativeInputManager的建構函式中,首先建立Java層的context、IMS所對應的Native層object。接下來會建立兩個很重要的物件:EventHub、InputManager。
EventHub是負責與Input硬體驅動層進行互動的物件,它遮蔽了底層驅動處理Input事件的過程並向上層提供介面,這也是軟體架構中常見的分層設計:下層的實現細節對上層透明,上層只需要呼叫下層提供的介面即可呼叫下層提供的服務,上層不需要關注下層的實現細節。
再來看看InputManager的建構函式:
可知InputManager的建構函式中主要是建立了InputReader、InputDispatcher兩個物件,並分別將這兩個物件作為引數建立了兩個執行緒:InputReaderThread、InputDispatcherThread。
這裡的Thread類是Android對Linux語意的phread又封裝了一層,InputReaderThread、InputDispatcherThread這兩個執行緒起來之後就會去呼叫相應的threadLoop進行執行緒工作。
從字面意思上理解,InputReader是負責讀取事件、InputDispatcher負責分發事件。那麼我們到這裡就可以大致推斷出Android Input系統的框架:
EventHub從硬體驅動層讀取Input資料-->Native的InputReader執行緒從EventHub讀取資料併發送給InputDispather執行緒-->Native InputDispatcher執行緒將Input資料分發給Java Framework相應的Input事件的接受者-->最終對應到View的Input事件分發上。
這就是Android Input系統的大體框架,後續會對每個流程進行詳細的分析。