Android 事件处理过程,(1)

来源:互联网 发布:html 数组 编辑:程序博客网 时间:2024/06/10 22:49

Android 事件处理过程

 

一、事件主要包括按键-keyEvent,触屏-motionEvent,

事件投递的过程分为几个部分,源信息的采集->WindowManagerService分配->应用程序处理。

Android通过访问/dev/input节点来获知当前发生的事件。

WindowManagerService是窗口的管理者,记录了系统中所有窗口的状态信息,所以它能够判断应该把事件投递到那个应用进程处理,按键事件直接发给最前端的窗口,触摸消息要先计算这个触目点落在那个区域,然后传给相应的窗口单元。

应用程序端的处理,针对按键事件,通过相应的监听处理,针对触摸事件,要依据View体系做事件分发。

 

输入系统的核心服务是InputManagerService,它是由SystemServer启动的,

private void startOtherServices()@SystemServer.java{

       InputManagerServiceinputManager = new InputManagerService(context);

       wm= WindowManagerService.main(context, inputManager,

              mFactoryTestMode!= FactoryTest.FACTORY_TEST_LOW_LEVEL,

              !mFirstBoot,mOnlyCore);

       ServiceManager.addService(Context.INPUT_SERVICE,inputManager);

 

       inputManager.setWindowManagerCallbacks(wm.getInputMonitor());

       inputManager.start();

}

1),从这里看出,InputManagerService和WindowManagerService是有联系的,因为事件的分发要先传到WindowManagerservice来分配给具体窗口,所以他们之间必然要有实例引用。

接着IMS把自己注册到ServiceManager。

2),通过setWindowManagerCallbacks设置了一个回调,参数是InputMonitor,这个InputMonitor实现的是InputManagerService中的接口WindowManagerCallbacks,是WMS跟IMS中InputDispatch之间沟通的桥梁,InputDispatch是负责事件分发的。

 

比如一个key事件的拦截,首先是InputDispatch(cpp)的函数dispatchKeyLocked,然后经有NativeInputManager(cpp)调用到InputManagerService.java(java)中的interceptKeyBeforeDispatching,再由InputManagerService.java中那个回调就是wm.getInputMonitor(),也即是mWindowManagerCallbacks,这样就到了WindowManagerService.java,InputMonitor是WMS的一个成员变量,最后由InputMonitor.java转到具体的窗口管理策略PhoneWindowManager.java中,执行实际的拦截处理。

 

3),最后调用了IMS的start方法,看一下start方法做了什么事情:

public void start()@InputManagerService.java{

       nativeStart(mPtr);

}

它主要调用了一个native方法,nativeStart,其中的参数mPtr是什么呢?这要看下IMS的构造函数。

public InputManagerService(Context context){

       mPtr= nativeInit(this, mContext, mHandler.getLooper().getQueue());

}

这里也是通过naive方法nativeInit完成的mPtr的赋值,接着看native实现

static jlongnativeInit(...)@com_android_server_input_InputManagerService.cpp{

       这个函数参数很长,就不写了

       NativeInputManager*im = new NativeInputManager(contextObj, serviceObj,

              messageQueue->getLooper());

}

这里创建一个native类型的NativeInputManager实例,从名字看它是一个native层的InputManager,看看它的构造函数:

NativeInputManager::NativeInputManager(jobjectcontextObj,

       jobjectserviceObj, const sp<Looper>& looper){

       sp<EventHub>eventHub = new EventHub();

       mInputManager= new InputManager(eventHub, this, this);

}

这里创建了EventHub,inputReader负责读取事件,但是InputReader并不是直接去读设备节点,而是通过EventHub来完成的,EventHub的本质是一个pipe,一个管道,它通过读取dev/input/event文件来判断是不是有新的事件,然后通知InputReader。

这个InputManager实例作为 NativeInputManager的一个成员,在IMS的start方法中会被调用。同时把EventHub作为参数传给了InputManager的构造函数。也就是IMS在native层的实现其实就是这个InputManager,这个从IMS的start方法的执行可以看出来。

接着前面说的IMS的start方法,调用的nativeStart,

static void nativeStart(JNIEnv* env, jclass/* clazz */, jlong ptr)                 @com_android_server_input_InputManagerService.cpp{

       NativeInputManager*im = reinterpret_cast<NativeInputManager*>(ptr);

       status_tresult = im->getInputManager()->start();

}

这里先通过 NativeInputManager得到mInputManager,然后调用其start方法。

status_tInputManager::start()@InputManager.cpp{

       status_tresult = mDispatcherThread->run("InputDispatcher",                           PRIORITY_URGENT_DISPLAY);

       result= mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);

}

可以看到start方法主要是启动了两个线程,这2个线程是在InputManager的构造函数中创建的。一个Inputreader负责从驱动节点读取Event,一个InputDispatch负责把event分发出去。

原创粉丝点击