Android輸入系統(tǒng)(一)輸入事件傳遞流程和InputManagerService的誕生

關(guān)聯(lián)系列
解析WMS系列
View體系系列

前言

很多同學(xué)可能會(huì)認(rèn)為輸入系統(tǒng)是不是和View的事件分發(fā)有些關(guān)聯(lián),確實(shí)是有些關(guān)聯(lián),只不過View事件分發(fā)只能算是輸入系統(tǒng)事件傳遞的一部分。這個(gè)系列講的輸入系統(tǒng)主要是我們不常接觸的,但還是需要去了解的那部分。

1. 輸入事件傳遞流程的組成部分

輸入系統(tǒng)是外界與Android設(shè)備交互的基礎(chǔ),僅憑輸入系統(tǒng)是無法完成輸入事件傳遞的,因此需要輸入系統(tǒng)和Android系統(tǒng)的其他成員來共同完成事件傳遞。輸入系統(tǒng)事件傳遞需要經(jīng)過以下幾個(gè)部分。


輸入事件傳遞流程可以大致的分為三個(gè)部分,分別是輸入系統(tǒng)部分、WMS處理部分和View處理部分。下面分別對(duì)這幾個(gè)部分進(jìn)行簡(jiǎn)單的介紹。

輸入系統(tǒng)部分

輸入系統(tǒng)部分主要又分為輸入子系統(tǒng)和InputManagerService組成(以下簡(jiǎn)稱IMS),在Android中還有一個(gè)IMS(IP Multimedia Subsystem)意為為IP多媒體子系統(tǒng),不要搞混了。
Android的輸入設(shè)備有很多種,比如屏幕、鍵盤、鼠標(biāo)、游戲手柄、操縱桿等等,其中應(yīng)用開發(fā)接觸最多的屏幕。當(dāng)輸入設(shè)備可用時(shí),Linux內(nèi)核會(huì)在/dev/input中創(chuàng)建對(duì)應(yīng)的設(shè)備節(jié)點(diǎn)。
用戶操作這些輸入設(shè)備時(shí)會(huì)產(chǎn)生各種事件比如按鍵事件、觸摸事件、鼠標(biāo)事件等。
輸入事件所產(chǎn)生的原始信息會(huì)被Linux內(nèi)核中的輸入子系統(tǒng)采集,原始信息由Kernel space的驅(qū)動(dòng)層一直傳遞到User space的設(shè)備節(jié)點(diǎn)。

Android提供了getevent和sendevent兩個(gè)工具幫助開發(fā)者從設(shè)備節(jié)點(diǎn)讀取輸入事件和寫入輸入事件。


IMS所做的工作就是監(jiān)聽/dev/input下的所有的設(shè)備節(jié)點(diǎn),當(dāng)設(shè)備節(jié)點(diǎn)有數(shù)據(jù)時(shí)會(huì)將數(shù)據(jù)進(jìn)行加工處理并找到合適的Window,將輸入事件派發(fā)給它。

WMS處理部分

Android解析WindowManagerService(一)WMS的誕生這篇文章中我講過WMS的職責(zé)有四種,如下圖所示。

WMS的職責(zé)之一就是輸入系統(tǒng)的中轉(zhuǎn)站,WMS作為Window的管理者,會(huì)配合IMS將輸入事件交由合適的Window來處理。

View處理部分

View處理部分應(yīng)該是大家最熟悉的了,一般情況下,輸入事件最終會(huì)交由View來處理,應(yīng)用開發(fā)者就可以通過一些回調(diào)方法輕松得到這個(gè)事件的封裝類并對(duì)其進(jìn)行處理,比如onTouchEvent(MotionEvent ev)方法。關(guān)于View體系可以查看View體系這一系列文章。

2. IMS的誕生

輸入事件傳遞流程的組成部分我們已經(jīng)了解了,本系列主要講解輸入系統(tǒng)部分中IMS對(duì)輸入事件的處理,在這之前我們需要了解IMS的誕生。

2.1 SyetemServer處理部分

與AMS、WMS、PMS一樣,IMS的在SyetemServer進(jìn)程中被創(chuàng)建的,SyetemServer進(jìn)程用來創(chuàng)建系統(tǒng)服務(wù),不了解它的可以查看 Android系統(tǒng)啟動(dòng)流程(三)解析SyetemServer進(jìn)程啟動(dòng)過程 這篇文章。
從SyetemServer的入口方法main方法開始講起,如下所示。
frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {
       new SystemServer().run();
   }

main方法中只調(diào)用了SystemServer的run方法,如下所示。
frameworks/base/services/java/com/android/server/SystemServer.java

private void run() {
  ...
    try {
        traceBeginAndSlog("StartServices");
        //啟動(dòng)引導(dǎo)服務(wù)
        startBootstrapServices();//1
        //啟動(dòng)核心服務(wù)
        startCoreServices();//2
        //啟動(dòng)其他服務(wù)
        startOtherServices();//3
        SystemServerInitThreadPool.shutdown();
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        traceEnd();
    }
    ...
}

在注釋1中的startBootstrapServices方法中用SystemServiceManager啟動(dòng)了ActivityManagerService、PowerManagerService、PackageManagerService等服務(wù)。在注釋2處的startCoreServices方法中則啟動(dòng)了DropBoxManagerService、BatteryService、UsageStatsService和WebViewUpdateService。注釋3處的startOtherServices方法中啟動(dòng)了CameraService、AlarmManagerService、VrManagerService等服務(wù)。這些服務(wù)的父類均為SystemService。從注釋1、2、3的方法可以看出,官方把系統(tǒng)服務(wù)分為了三種類型,分別是引導(dǎo)服務(wù)、核心服務(wù)和其他服務(wù),其中其他服務(wù)是一些非緊要和一些不需要立即啟動(dòng)的服務(wù)。這些系統(tǒng)服務(wù)總共有100多個(gè),我們熟知的AMS和PMS屬于引導(dǎo)服務(wù),WMS屬于其他服務(wù)。
本文要講的IMS屬于其他服務(wù),這里列出其他服務(wù)以及它們的作用,見下表。

其他服務(wù) 作用
CameraService 攝像頭相關(guān)服務(wù)
AlarmManagerService 全局定時(shí)器管理服務(wù)
InputManagerService 管理輸入事件
WindowManagerService 窗口管理服務(wù)
VrManagerService VR模式管理服務(wù)
BluetoothService 藍(lán)牙管理服務(wù)
NotificationManagerService 通知管理服務(wù)
DeviceStorageMonitorService 存儲(chǔ)相關(guān)管理服務(wù)
LocationManagerService 定位管理服務(wù)
AudioService 音頻相關(guān)管理服務(wù)
... ....

查看啟動(dòng)其他服務(wù)的注釋3處的startOtherServices方法。
frameworks/base/services/java/com/android/server/SystemServer.java

  private void startOtherServices() {
  ...
            inputManager = new InputManagerService(context);//1
            traceEnd();
            traceBeginAndSlog("StartWindowManagerService");
            // WMS needs sensor service ready
            ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
            mSensorServiceStart = null;
            wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore, new PhoneWindowManager());//2
            ServiceManager.addService(Context.WINDOW_SERVICE, wm);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
            traceEnd();
 ...           

 }

注釋1處創(chuàng)建了IMS,注釋2處執(zhí)行了WMS的main方法,其內(nèi)部會(huì)創(chuàng)建WMS。需要注意的是,main方法的其中一個(gè)參數(shù)就是注釋1處創(chuàng)建的IMS,在本地第1節(jié)中我們知道WMS是輸入系統(tǒng)的中轉(zhuǎn)站,其內(nèi)部包含了IMS引用并不意外。緊接著將WMS和IMS添加到ServiceManager中進(jìn)行統(tǒng)一的管理。

2.2 InputManagerService構(gòu)造方法

我們接著來查看IMS的構(gòu)造方法。
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());//1
        mUseDevInputEventForAudioJack =
                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                + mUseDevInputEventForAudioJack);
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());//2

        ...
    }

注釋1處用android.display線程的Looper創(chuàng)建了InputManagerHandler,這樣InputManagerHandler會(huì)運(yùn)行在android.display線程,android.display線程是系統(tǒng)共享的單例前臺(tái)線程,這個(gè)線程內(nèi)部執(zhí)行了WMS的創(chuàng)建,具體見 Android解析WindowManagerService(一)WMS的誕生這篇文章。
注釋2處調(diào)用了nativeInit方法,很明顯是要通過JNI調(diào)用Navive方法。
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());//1
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

注釋1處創(chuàng)建了NativeInputManager,最后會(huì)調(diào)用reinterpret_cast運(yùn)算符將NativeInputManager指針強(qiáng)制轉(zhuǎn)換并返回(重新解釋比特位)。NativeInputManager的構(gòu)造函數(shù)如下所示。
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    ...
    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}

NativeInputManager構(gòu)造函數(shù)中創(chuàng)建了EventHub和InputManager,EventHub通過Linux內(nèi)核的INotify與Epoll機(jī)制監(jiān)聽設(shè)備節(jié)點(diǎn),通過EventHub的getEvent函數(shù)讀取設(shè)備節(jié)點(diǎn)的增刪事件和原始輸入事件,本系列后續(xù)文章會(huì)詳細(xì)介紹EventHub。InputManager的構(gòu)造函數(shù)如下所示。
frameworks/native/services/inputflinger/InputManager.cpp

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}

void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

InputManager構(gòu)造函數(shù)中創(chuàng)建了InputReader和InputDispatcher,InputReader會(huì)不斷循環(huán)讀取EventHub中的原始輸入事件,將這些原始輸入事件進(jìn)行加工后交由InputDispatcher,InputDispatcher中保存了WMS中的所有Window信息(WMS會(huì)將窗口的信息實(shí)時(shí)的更新到InputDispatcher中),這樣InputDispatcher就可以將輸入事件派發(fā)給合適的Window。InputReader和InputDispatcher都是耗時(shí)操作,因此在initialize函數(shù)中創(chuàng)建了供它們運(yùn)行的線程InputReaderThread和InputDispatcherThread。
InputManagerService構(gòu)造方法描繪了如下的IMS簡(jiǎn)圖。

從上面的簡(jiǎn)圖可以看出來,IMS主要的工作都在Native層中,這些內(nèi)容會(huì)在本系列的后續(xù)文章進(jìn)行介紹。

感謝
《深入理解Android》卷3
《深入理解Android內(nèi)核設(shè)計(jì)思想》
https://blog.csdn.net/u013604527/article/details/53432623
https://www.cnblogs.com/deng-tao/p/6094049.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容