1. 程式人生 > >Android Input系統原始碼分析一(啟動與初始化)

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系統的大體框架,後續會對每個流程進行詳細的分析。