向/dev/input/eventx的触摸设备写入实现高效安卓模拟触摸
向/dev/input/eventx
的触摸设备写入实现高效安卓模拟触摸
简介
android模拟触摸有很多种方式,比如在shell里可以使用input命令或者更接近底层的sendevent来模拟各种触摸事件.
然而它们的共性就是经过了多层封装,调用效率会很低.如果想要高速地注入触摸事件(每秒约100个触摸点),这种方法就很不现实了.
那不如干脆自己用纯C实现一个内部的sendevent,这样效率就能有很大提升,每秒上千个触摸点不在话下(不过这么多会让安卓躺平全部丢掉)
以下推荐先了解linux的触摸协议,高考生时间有限不再展开,且向eventX在当前主流高版本安卓写入需要root权限(用户input组内,而shell不在此列)
Linux输入子系统:多点触控协议 – multi-touch-protocol.txt【转】 - Sky&Zhang - 博客园
从sendevent开始
使用sendevent模拟一个简略的触摸事件如下:
1 |
|
以上例子实现了短暂点按(500,500)的效果.想要模拟触摸只需要按顺序向event2写入这些数据即可.
同样的,我们还能模拟手指在屏幕上的方向\压力等,这里不再赘述.
需要注意的是,触摸屏的坐标和屏幕显示的坐标不一定相同,在本人手机上这个比是1,而在学校电脑上x和y的比例分别为18和32,屏幕坐标需要乘以这两个比例才能转化到触摸事件的坐标,该比例可以通过getevent -i
查到:
1 |
|
可以看到xy被映射到(32767,32767)的触摸范围,比例就是resolution+1.
sendevent的代码很简单,甚至到了简陋的地步,它是toybox的一部分:
toybox/toys/android/sendevent.c at master · landley/toybox · GitHub
1 |
|
由此可见只需要构建一个input_event struct然后直接写到设备就能实现事件注入.
实践
在我的彩蛋项目里,我构建了一个简陋的框架:
printer.h的一部分:
1 |
|
printer.c的一部分:
1 |
|
效果
以下视频原速播放
原图边界:
画了两次,用来解决每个边界都不太全的问题.