源码角度分析Android的事件输入系统(input system)及ANR原理分析

此篇我们从android5.0(lolipop)源码角度分析Android的事件输入系统(input system):

先引用一张图来说明下,Android输入系统的整个流程:




1、Linux内核,接受输入设备的中断,并将原始事件的数据写入到设备节点中。
2、设备节点,作为内核与IMS的桥梁,它将原始事件的数据暴露给用户空间,以便IMS可以从中读取事件。
3、 InputManagerService,一个Android系统服务,它分为Java层和Native层两部分。Java层负责与WMS的通 信。而Native层则是InputReader和InputDispatcher两个输入系统关键组件的运行容器。
4、EventHub,直接访问所有的设备节点。并且正如其名字所描述的,它通过一个名为getEvents()的函数将所有输入系统相关的待处理的底层事件返回给使用者。这些事件包括原始输入事件、设备节点的增删等。
5、InputReader,I是IMS中的关键组件之一。它运行于一个独立的线程中,负责管理输入设备的列表与配置,以及进行输入事件的加工处理。它通过其线程循环不断地通过getEvents()函数从EventHub中将事件取出并进行处理。对于设备节点的增删事件,它会更新输入设备列表于配置。对于原始输入事件,InputReader对其进行翻译、组装、封装为包含了更多信息、更具可读性的输入事件,然后交给InputDispatcher进行派发。
6、InputReaderPolicy,它为InputReader的事件加工处理提供一些策略配置,例如键盘布局信息等。
7、InputDispatcher,是IMS中的另一个关键组件。它也运行于一个独立的线程中。InputDispatcher中保管了来自WMS的所有窗口的信息,其收到来自InputReader的输入事件后,会在其保管的窗口中寻找合适的窗口,并将事件派发给此窗口。
8、InputDispatcherPolicy,它为InputDispatcher的派发过程提供策略控制。例如截取某些特定的输入事件用作特殊用途,或者阻止将某些事件派发给目标窗口。一个典型的例子就是HOME键被InputDispatcherPolicy截取到PhoneWindowManager中进行处理,并阻止窗口收到HOME键按下的事件。
9、WMS,虽说不是输入系统中的一员,但是它却对InputDispatcher的正常工作起到了至关重要的作用。当新建窗口时,WMS为新窗口和IMS创建了事件传递所用的通道。另外,WMS还将所有窗口的信息,包括窗口的可点击区域,焦点窗口等信息,实时地更新到IMS的InputDispatcher中,使得InputDispatcher可以正确地将事件派发到指定的窗口。
10、  ViewRootImpl,对于某些窗口,如壁纸窗口、SurfaceView的窗口来说,窗口即是输入事件派发的终点。而对于其他的如Activity、对话框等使用了Android控件系统的窗口来说,输入事件的终点是控件(View)。ViewRootImpl将窗口所接收到的输入事件沿着控件树将事件派发给感兴趣的控件
Linux内核对硬件中断的处理超出了本书的讨论范围,因此本章将以IMS为重点,详细讨论除Linux内核以外的其他参与者的工作原理。

接下来我们就来看看 IMS的启动过程,探讨IMS的构成
IMS分为Java层与Native层两个部分
InputManagerService 源码 位于以下路径:

IMS的主要作用:
它用于管理整个系统的输入部分,包括键盘、鼠标、触摸屏等等。
IMS和其他的系统服务一样,都是在SystemServer中创建的,具体流程如下:
SystemServer中初始化IMS,然后初始化WMS,把IMS作为参数传入
Slog.i(TAG, "Input Manager");
inputManager = new InputManagerService(context);

Slog.i(TAG, "Window Manager");
wm = WindowManagerService.main(context, inputManager,
     mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
     !mFirstBoot, mOnlyCore);
 // 将IMS发布给ServiceManager,以便其他人可以访问IMS提供的接口
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);

mActivityManagerService.setWindowManager(wm);
// 设置向WMS发起回调的callback对象
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
 //  正式启动IMS
inputManager.start();

IMS的诞生分为两个阶段:

·  创建新的IMS对象。

·  调用IMS对象的start()函数完成启动。

接下来看IMS构造函数如下:
public InputManagerService(Context context) {
   this.mContext = context;
   this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

   mUseDevInputEventForAudioJack =
           context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
   Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
           + mUseDevInputEventForAudioJack);
   mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());

   LocalServices.addService(InputManagerInternal.class, new LocalService());
}



构造方法中值得注意的点:获取 DisplayThread的looper,说明InputManagerHandler运行在DisplayThread所在线程中
调用c++层的 nativeInit方法,传入InputManagerService自己和looper中的messageQueue ;
nativeInit方法如下:
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值