input事件处理流程

0.前言

Android input事件基本可以分为input事件的获取以及input的事件分发这两个过程,那么我们就从这两个方面进行分析。

首先input事件肯定是从你点击屏幕或者按下了某个按键或者触发了屏幕旋转等事件开始的,但是这些基本都已经和硬件已经强相关了,我们也就不需要去了解这些。就从systemserver开始创建inputmanagerservice(以下简称ims)开始吧。

ps.本文基于9.0代码

1.input事件的获取

首先我们从systemserver创建ims的地方开始吧:

724    private void startOtherServices() {
    //去掉了无关的代码
853            traceBeginAndSlog("StartInputManagerService");
     //创建ims
854            inputManager = new InputManagerService(context);
855            traceEnd();
856
857            traceBeginAndSlog("StartWindowManagerService");
858            // WMS needs sensor service ready
859            ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
860            mSensorServiceStart = null;
    //创建wms
861            wm = WindowManagerService.main(context, inputManager,
862                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
863                    !mFirstBoot, mOnlyCore, new PhoneWindowManager());
864            ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
865                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
866            ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
867                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
868            traceEnd();
869
870            traceBeginAndSlog("SetWindowManagerService");
871            mActivityManagerService.setWindowManager(wm);
872            traceEnd();
873
874            traceBeginAndSlog("WindowManagerServiceOnInitReady");
875            wm.onInitReady();
876            traceEnd();
877
878            // Start receiving calls from HIDL services. Start in in a separate thread
879            // because it need to connect to SensorManager. This have to start
880            // after START_SENSOR_SERVICE is done.
881            SystemServerInitThreadPool.get().submit(() -> {
882                TimingsTraceLog traceLog = new TimingsTraceLog(
883                        SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
884                traceLog.traceBegin(START_HIDL_SERVICES);
885                startHidlServices();
886                traceLog.traceEnd();
887            }, START_HIDL_SERVICES);
888
889            if (!isWatch) {
890                traceBeginAndSlog("StartVrManagerService");
891                mSystemServiceManager.startService(VrManagerService.class);
892                traceEnd();
893            }
894
    //将wms的monitor传给ims作为回调
895            traceBeginAndSlog("StartInputManager");
896            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
897            inputManager.start();
898            traceEnd();
899

这里可以看到systemserver创建了ims以及wms,并将wms中的monitor传给了ims,作为回调。

关键的两个操作就是新建ims以及ims的start操作。

然后就可以看一下ims初始化的时候具体是做了哪些操作:

314    public InputManagerService(Context context) {
// ...
322        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
323
//...
330    }

关键内容就是调用jni方法init了native的函数。于是我们再来看一下ims的start操作

340    public void start() {
//...
342        nativeStart(mPtr);
343
//...
363    }

恩,同样很关键的调用了native的start方法。看来其实都是与native相关的内容。那么在native的具体内容。

1231static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
1232        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
1233    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
1234    if (messageQueue == NULL) {
1235        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
1236        return 0;
1237    }
1238//很关键的创建了一个nativeinputmanager实例,并且和java层使用的是同一个looper
1239    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
1240            messageQueue->getLooper());
1241    im->incStrong(0);
1242    return reinterpret_cast<jlong>(im);
1243}
1245static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
1246    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1247
1248    status_t result = im->getInputManager()->start();
1249    if (result) {
1250        jniThrowRuntimeException(env, "Input manager could not be started.");
1251    }
1252}

在init的时候创建了一个nativeinputmanager实例.

321NativeInputManager::NativeInputManager(jobject contextObj,
322        jobject serviceObj, const sp<Looper>& looper) :
323        mLooper(looper), mInteractive(true) {
...
339    sp<EventHub> eventHub = new EventHub(); //创建了一个eventhub,同时将这个eventhub传给新建的inputmanager
340    mInputManager = new InputManager(eventHub, this, this);
341}

eventhub就是将数据从硬件驱动上读出来然后传递上来的通道,同时,我们可以看到:

27InputManager::InputManager(
28        const sp<EventHubInterface>& eventHub,
29        const sp<InputReaderPolicyInterface>& readerPolicy,
30        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
31    mDispatcher = new InputDispatcher(dispatcherPolicy);
32    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
33    initialize();
34}
48void InputManager::initialize() {
49    mReaderThread = new InputReaderThread(mReader);
50    mDispatcherThread = new InputDispatcherThread(mDispatcher);
51}

创建了inputdispatcher和inputreader,但是这两者都是通过之前的nativeinputmanager,因为inputmanager实现了这两个接口。

189class NativeInputManager : public virtual RefBase,
190    public virtual InputReaderPolicyInterface,//重要接口
191    public virtual InputDispatcherPolicyInterface,//另一个重要接口
192    public virtual PointerControllerPolicyInterface {

好了,那么此时inputread和inputdispatch已经连接在一起了,那么我们可以看一下inputmanager->start是一个什么样的过程呢。

53status_t InputManager::start() {
54    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
55    if (result) {
56        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
57        return result;
58    }
59
60    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
61    if (result) {
62        ALOGE("Could not start InputReader thread due to error %d.", result);
63
64        mDispatcherThread->requestExit();
65        return result;
66    }
67
68    return OK;
69}

所以inputmanager的start就是将这两个threadrun起来。那么现在我们就可以总结一下:

1.首先systemserver启动了ims

2.ims通过nativeinit初始化了nativeinputmanager和底层的inputmanager

3.inputmanager中有reader和dispatcher,在inputmanager中结合

4.ims通过nativestart方法将两个thread开始了循环

下面是对应的UML时序图:

初始化的时序图