Android input events 输入系统

前言

本文代码基于 Android 12 。

概述

Android 的事件输入可以简化为三部分:

  1. 物理输入设备 -> InputDispatcher
  2. InputDispatcher -> ViewRootImpl
  3. ViewRootImpl 事件派发

物理输入设备 -> InputDispatcher

这一部分主要有三个流程:

  1. 物理输入设备 -> 标准的 Linux 输入事件
  2. 标准的 Linux 输入事件 -> Android 输入事件
  3. Android 输入事件 -> Android 显示器上的窗口

物理输入设备 -> 标准的 Linux 输入事件

这一部分主要由 Linux 内核中的输入设备驱动程序完成:
物理设备生成输入事件信号后,会由设备固件编码成设备特有的事件信号,并传输给 Linux 系统,再由 Linux 内核中的输入设备驱动程序解码成标准的 Linux 输入事件格式。

标准的 Linux 输入事件 -> Android 输入事件

这一部分主要由 Android InputReader 实现:
Android EventHub 组件会打开与每个输入设备关联的 evdev 驱动程序并从 Linux 内核中读取这些标准的输入事件,再由 Android InputReader 组件根据设备类别解码成 Android 定义的事件。

Android 输入事件 -> Android 显示器上的窗口

该部分主要由 Android InputDispatcher 组件完成:
Android InputReader 会把生成的 Android 输入事件流发送给 InputDispatcher ,然后由 InputDispatcher 将这些事件转发给对应的窗口。

如图:


输入管道

根据物理输入设备的不同,Android 输入事件主要分为 KeyEvent 和 MotionEvent 。


MotionEvent && KeyEvent

所以用来上传 KeyEvent 的设备有物理键盘设备、DPad 等。而上传 MotionEvent 的设备有显示屏设备、鼠标、手写笔等。

InputDispatcher -> ViewRootImpl

InputDispatcher 是怎么把事件转发给对应的窗口呢?
答:app 在向系统添加窗口时,会和系统进程建立 socket 连接,系统进程将 service 端的 socket 传送到 InputDispatcher ,把 client 端的 socket 返回给 app 。当事件到达时,InputDispatcher 找到此时具有焦点的窗口,通过 socket 把事件发送该 socket 。

如图:
InputDispatcher -> ViewRootImpl

在此过程中,socket 会被封装成 InputChannel :


InputChannel

设置 InputChannel 的流程:


设置 InputChannel

可以看到,在添加窗口时,IMS 向 linux 系统请求创建一对 socket 并封装成 InputChannel ,server 端的留在 InputDispatcher ,client 端的传送给 app 端的 ViewRootImpl 。因此 events 可以直接从 InputDispatcher 分发给对应的 ViewRootImpl 。
简述:
InputDispatcher 和 窗口通过 InputChannel 交互

那剩下就是如何找到合适的窗口(ViewRootImp)派发事件?
答:InputDispatcher 保存了系统中每个窗口 layer 的信息,包括这个窗口是否可见、是否可以接收输入事件、是否聚焦等。在事件派发时,只要找到当前聚焦的窗口的 InputChannel 并通过它发给目标窗口即可。而窗口的信息由 WMS 通过 InputMonitor 更新到 InputDispatcher 中。如图:


WMS -> InputMonitor -> InputDispatcher 设置 InputWindowHandle

其中聚焦的信息封装在 FocusRequest 中:
FocusRequest

其流程可概括为:
设置 focused app 和 window 流程

具体流程为:
设置 focused window

总结,InputDispatcher 和 ViewRootImpl 之间的交互过程如图:


InputDispatcher ViewRootImpl 事件交互

具体流程为:


InputDispatcher 事件派发

ViewRootImpl 事件派发

窗口是怎么把事件转发给正确的 view 呢?
答:ViewRootImpl 封装了一系列的 InputStage 来处理输入事件,这些 InputStage 组成链式结构,如果上一个节点的 InputStage 没处理则传给下个节点处理。在 InputStage 中通过事件类型来区分怎么处理,一般来说 Listener 比 View 先处理。如,事件为 KeyEvent 时,OnKeyListener 先处理,再是 View 处理 onKeyDown、onKeyUp 等。
简要概括流程为:


app 分配 input event 流程

其中 InputStage 的处理顺序为:


ViewRootImp InputStage 处理顺序

事件类型分为:
事件类型

以 pointer 事件和 key 事件为例其具体流程如下:
ViewRootImpl 派发事件流程

总结

简要概述一下 Android 事件的流程就是:

  1. Linux 内核中的输入设备驱动程序将物理输入设备产生的输入信号转换成标准 Linux 输入事件格式;
  2. Android EventHub 组件打开与每个输入设备关联的 evdev 驱动程序,并从 Linux 内核中读取已转成标准 Linux 输入事件格式的输入信号,再通过 Android 的 InputReader 组件转码成 Android 事件输入流并发送给 InputDispatcher。
  3. InputDispatcher 将事件通过 socket 发送给系统当前聚焦的窗口。
  4. 窗口将事件派发给需要处理这个事件的 view,如 Touch Event 派发给当前 window 中管辖触摸点 [x,y] 的最小的可接收事件的 View ,而 Key Event 派发给当前窗口中聚焦的 View 。

参考

Android 官方:输入
《深入理解 Android 内核设计思想》上,著:林学森
Android 官方代码

原创文章,欢迎转载,但请注明出处

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容