背景
相较于传统的键盘输入的繁琐,移动智能终端提供了更加便捷的交互方式,只需要简单的点击和滑动就可以实现非常复杂的功能。如下图所示,当你的女朋友按下“立即购买”按钮的时候,除了让你的支付宝余额减少之外又发生了什么?这些点击和滑动的背后又隐藏着什么样的秘密?本文章将会一一揭晓。
文章图片
故事的开始
那是一个疫情隔离的下午,你的女朋友百无聊赖地躺在沙发上逛京东,突然看到了苹果发布的iPhone13新款,看了看手里略显卡顿的iPhone12,在经过了反复的思考(0.00001秒)之后,十分纠结(毫不犹豫)地按下了立即购买,在她的手指触碰到手机屏幕的那一刻究竟发生了什么?我们先来看一下案发现场,那是一块常见手机屏幕,那么它又是如何对你女朋友的操作心领神会的呢?现在的智能手机屏幕主要包含以下三个部分,盖板玻璃是手机屏幕最外层的部件,起到保护手机内部结构的作用。触控模组可实现触控感应,是提升人机交互体验的关键。手机屏幕基本以电容式触摸屏为主。触摸感应层下面是前面板,主要用来安装滤光片,生成图像;再下一层是背板,用来处理薄膜晶体管。显示模组主要以LCD和OLED为主,是两种最主流的手机屏幕种类。LCD屏幕显示模组由偏光片、彩色滤光片、TFT、液晶、背板等构成,图像显色度好、画面柔和不伤眼,是当前应用最广泛的手机显示屏幕;OLED屏幕显示模组由偏光片、有机发光层、玻璃、TFT等材料构成,屏幕可自发光,具有轻薄、可弯曲、低耗能的优点,是目前新兴的屏幕显示技术。其中就是电容式触摸屏将负责传达你女朋友的点击意图,那么它又是如何实现的呢?
其实对于触摸屏而言并不知道你女朋友点击的是“加入购物车”还是“立即购买”或者其他内容,其实可以把触摸屏想象成一个二维的坐标系,触摸屏知道的只是你女朋友点击的坐标,触摸屏的工作原理概括来说就是上报坐标值,X轴、Y轴的值。其过程如下图所示,电容屏通过任何持有电荷的物体包括人体皮肤工作。(人体所带的电荷)电容式触摸屏是由诸如合金或是銦錫氧化物(ITO)这样的材料构成,电荷存储在一根根比头发还要细的微型静电网中。当手指点击屏幕,会从接触点吸收小量电流,造成角落电极的压降,利用感应人体微弱电流的方式来达到触控的目的。(这是为什么当你戴上手套触摸屏幕时,没有反应的原因),然后通过触摸屏中的触控IC计算出坐标。
文章图片
童年:从硬件走向系统
谁人能想到这一次简单的碰撞会擦出如此的火花,如果将这样的一次操作映射为人的一生,那么“立即购买”此时刚呱呱坠地,而它背后的坐标就如同它的生辰八字,而这个生辰八字也将深深地影响它的一生,至于是如何影响的对于它来说那将会是很久以后的事情,我们暂时不表,先看看它现在面对的困境:如何从硬件走向系统。众所周知Android是基于Linux系统的,所以Android对于用户输入的处理依然是沿用Linux的输入子系统.工作机理是底层在按键、触摸等动作发生时产生一个中断(或驱动timer定时查询),然后CPU通过SPI、I2C或外部存储器总线读取键值,坐标等数据。
Linux内核为了能够处理各种不同类型的输入设备,比如 触摸屏、鼠标、键盘、操纵杆,设计并实现了为驱动层程序的实现提供统一接口函数,为上层应用提供统一的抽象层,即是Linux 输入子系统。如下图所示,Linux输入子系统主要包含三个部分Input driver(设备驱动层)、Input core(输入核心层)、Event handler(事件处理层)。“立即购买”诞生之后会依次通过Input driver、Input core和Event handler最后到达用户空间。输入子系统是所有I/O设备驱动的中间层,为上层提供了一个统一的界面。例如,在终端系统中,我们不需要去管有多少个键盘,多少个鼠标。它只要从输入子系统中去取对应的事件(按键,鼠标移位等)就可以了。
- Input driver :主要实现对硬件设备的读写访问,中断设置,并把硬件产生的事件转换为核心层定义的规范提交给事件处理层。
- Input core :承上启下。为设备驱动层提供了规范和接口,通知事件处理层对事件进行处理;
- Event handler :提供用户编程的接口(设备节点),并处理驱动层提交的数据处理。
文章图片
事件 | 事件码 | 解释 |
---|---|---|
EV_SYN | 0x00 | 同步事件 |
EV_KEY | 0x01 | 按键事件 |
EV_REL | 0x02 | 相对坐标(如:鼠标移动,报告相对最后一次位置的偏移) |
EV_ABS | 0x03 | 绝对坐标(如:触摸屏或操作杆,报告绝对的坐标位置) |
EV_MSC | 0x04 | 其它 |
EV_SW | 0x05 | 开关 |
EV_LED | 0x11 | 按键/设备灯 |
EV_SND | 0x12 | 声音/警报 |
EV_REP | 0x14 | 重复 |
EV_FF | 0x15 | 力反馈 |
EV_PWR | 0x16 | 电源 |
EV_FF_STATUS | 0x17 | 力反馈状态 |
EV_MAX | 0x1f | 事件类型最大个数和提供位掩码支持 |
- input_reprot_abs(input_dev,ABS_X,x);上报x坐标
- input_reprot_abs(input_dev,ABS_Y,y); 上报y坐标
- input_reprot_abs(input_dev,ABS_PRESSURE,1); 上报压力
- input_sync(input_dev);
同步结束
下面这张图可以更形象的说明这个过程,通过Linux的输入子系统,“立即购买”完成了从硬件到内核最后到到用户空间的过程。
文章图片
在Android中是存在/dev/input/event* 设备节点中,Android SDK中还提供了getevent工具可以查看设备下挂载的输入设备以及查看设备节点中的输入数据。
root@rk3288:/ # getevent
getevent
add device 1: /dev/input/event3
name:"ILITEK Multi-Touch-V3020"
add device 2: /dev/input/event2
name:"PC Camera"
add device 3: /dev/input/event1
name:"gsensor"
add device 4: /dev/input/event0
name:"rk29-keypad"root@rk3288:/ # ls /dev/input
ls /dev/input
event0
event1
event2
event3
// 读取 event3 数据(触摸屏)
root@rk3288:/ # getevent -t /dev/input/event3
getevent -t /dev/input/event3
[1141.248434] 0003 0039 0000000e
[1141.248434] 0003 0035 00002cd4
[1141.248434] 0003 0036 00001a09
[1141.248434] 0001 014a 00000001
[1141.248434] 0003 0000 00002cd4
[1141.248434] 0003 0001 00001a09
[1141.248434] 0000 0000 00000000
[1141.322181] 0003 0039 ffffffff
[1141.322181] 0001 014a 00000000
[1141.322181] 0000 0000 00000000
上面就是“立即购买”存储在设备节点中的形式,[ 1141.248434] 0003 0039 0000000e为例说明一下其中的含义,其中[1141.248434]是时间戳,0003是事件类型,0039是事件码,0000000e是事件的值。getevent以文本形式输出事件类型和名称,其结果如下
root@rk3288:/ # getevent -l /dev/input/event3
getevent -l /dev/input/event3 // 事件类型事件码事件值
EV_ABSABS_MT_TRACKING_ID0000000f
EV_ABSABS_MT_POSITION_X00002bbc
EV_ABSABS_MT_POSITION_Y00001b6d
EV_KEYBTN_TOUCHDOWN
EV_ABSABS_X00002bbc
EV_ABSABS_Y00001b6d
EV_SYNSYN_REPORT 00000000 EV_ABSABS_MT_TRACKING_IDffffffff
EV_KEYBTN_TOUCHUP
EV_SYNSYN_REPORT 00000000
正如之前所提到的,“立即购买”会以EV_ABS事件传递,存储的就是它的绝对坐标。经过以上分析,我们已经跟随着“立即购买”的脚步从硬件到内核,最后到了用户空间,算是走完了它童年,那么接下来又将面对什么样的挑战呢?让我们拭目以待。
最后 【Android(记录“立即购买”短暂的一生(上))】有兴趣可以关注公众号QStack,会不定期分享一些文章和学习资源。
推荐阅读
- Android IO流程你真的清楚了吗|硬核科普
- android|android 监控id代码,茗伊插件 剑三技能监控代码
- Android|摄像头 - 对焦算法实现总结
- FIT2081讲解
- Android进阶|Android进阶——组件化开发实践(二)
- android|初学Android网络封装
- 安卓移动|The emulator process for AVD Pixel_XL_API_29 was killed
- Android模拟器启动失败 The emulator process for AVD was killed.
- Kotlin|Kotlin Android Extensions遭废弃,官方推荐使用ViewBinding