Android UI自动化-InputEvent Record

在工作过程中,部分项目收到客户反馈,出现偶发性Crash,为了尽可能的复现客户问题,需要在程序内模拟用户输入,比如拍照,切换模式,切换分辨率,开关HDR模式等,之前有大概介绍过,目前在Android上做这类UI测试的几种主要方式:

  • 利用espresso,uiautomator等UI测试框架去寻找特定的View,并执行对应操作。优点是:应用场景全面,包括普通的点击滑动,还有自动输入等高级操作;大概率可以忽略屏幕适配的问题;可以在user版本运行。缺点:学习成本较高;复杂场景脚本维护工作了较大。
  • 利用adb shell input x y 的方式去模拟用户点击,组合操作可以通过脚本的方式完成。优点:方便实用;快。缺点:复杂场景脚本的设计会比较艰难,需要连接PC。
  • 因为Android也是类Linux系统,可以模拟鼠标等驱动事件,直接往Linux底层写事件。优点:可以进行事件等录制,适应场景极多;快速。缺点:学习成本较高。

考虑到我们的场景,以及后面还有类似的项目问题,所以我们选择了第三种,可以录制用户操作,然后按照录制的操作开始循环执行的方式。

1.原理分析

1.1.Android界面点击事件流程

用户在屏幕上点击一下后,程序里面的OnClickListener是怎样收到这个事件的。大致流程如下 :

用户点击 -> (硬件驱动部分)硬件产生一个中断 -> /dev/input/event* 写入一个相应的信号 -> jni部分 android循环读取/dev/input/event的事件 -> 分发给WindowManagerServer -> 最后再发到相应的ViewGroup和View。

这里我们就可以通过往/dev/input/event* 写信号的方式,来达到模拟事件的目的。

1.2.触摸协议分析

在2,1中,我们知道可以通过模拟的方式来达到我们模拟事件的目的,但是有个问题在于,事件的种类分为很多种,比如物理按键事件,触摸屏事件,蓝牙等,此处我们重点分析触摸屏事件。

触摸协议分单点触摸和多点触摸。以单点触摸为例,打开手机,同样关闭自动旋屏,输入adb shell getevent,鼠标点击一下屏幕,要足够快,不然数据太多。得到输出和下面类似。

[min@bogon:] ~ $ adb shell getevent
could not get driver version for /dev/input/mouse0, Not a typewriter
could not get driver version for /dev/input/mice, Not a typewriter
add device 1: /dev/input/event6
  name:     "huawei,ts_kit"
add device 2: /dev/input/event0
  name:     "soundtrigger_input_dev"
add device 3: /dev/input/event2
  name:     "hisi_on"
add device 4: /dev/input/event3
  name:     "minibugreport_key"
add device 5: /dev/input/event4
  name:     "fingerprint"
add device 6: /dev/input/event5
  name:     "hi3xxx_hi6405_card Headset Jack"
add device 7: /dev/input/event1
  name:     "hisi_gpio_key"
/dev/input/event6: 0003 003a 00000033
/dev/input/event6: 0003 0035 00000251
/dev/input/event6: 0003 0036 000002f2
/dev/input/event6: 0003 0039 00000000
/dev/input/event6: 0000 0002 00000000
/dev/input/event6: 0001 014a 00000001
/dev/input/event6: 0000 0000 00000000
/dev/input/event6: 0003 003a 00000033
/dev/input/event6: 0003 0035 00000251
/dev/input/event6: 0003 0036 000002f2
/dev/input/event6: 0003 0039 00000000
/dev/input/event6: 0000 0002 00000000
/dev/input/event6: 0000 0000 00000000
/dev/input/event6: 0003 003a 00000034
/dev/input/event6: 0003 0035 00000251
/dev/input/event6: 0003 0036 000002f2
/dev/input/event6: 0003 0039 00000000
/dev/input/event6: 0000 0002 00000000
/dev/input/event6: 0000 0000 00000000
/dev/input/event6: 0003 003a 00000034
/dev/input/event6: 0003 0035 00000251
/dev/input/event6: 0003 0036 000002f2
/dev/input/event6: 0003 0039 00000000
/dev/input/event6: 0000 0002 00000000
/dev/input/event6: 0000 0000 00000000

可单点触摸的协议每次点击会写6条信号,按照这个的格式:type code value,具体type含义,在本段末尾有贴出,结合type说明分析单点触摸事件如下:

/dev/input/event0: 0003 0000 00000117 EV_ABS ABS_X 0x117

触摸点的x坐标

/dev/input/event0: 0003 0001 0000020f EV_ABS ABS_Y 0x20f

触摸点的y坐标

/dev/input/event0: 0001 014a 00000001 EV_KEY BTN_TOUCH 1

touch down

/dev/input/event0: 0000 0000 00000000 EV_SYN 0 0 

同步信号量

/dev/input/event0: 0001 014a 00000000 EV_KEY BTN_TOUCH 0

touch up

/dev/input/event0: 0000 0000 00000000 EV_SYN 0 0

同步信号量

其中,type定义如下:
/* 
* Event types 
*/ 
#define EV_SYN 0x00 
#define EV_KEY 0x01 
#define EV_REL 0x02 
#define EV_ABS 0x03 
#define EV_MSC 0x04 
#define EV_SW 0x05 
#define EV_LED 0x11 
#define EV_SND 0x12 
#define EV_REP 0x14 
#define EV_FF 0x15 
#define EV_PWR 0x16 
#define EV_FF_STATUS 0x17 
#define EV_MAX 0x1f 
#define EV_CNT (EV_MAX+1)

常用的是EV_KEY, EV_REL, EV_ABS, EV_SYN分别对应按键, 相对坐标, 绝对坐标, 同步事件。
EV_SYN则表示一组完整事件完成上报,需要处理。

1.3.可行性验证

那么具体等事件分析已经结束,我们是否可以将这些事件写入对应的/dev/input/event* 来达到我们模拟事件点击的目的呢?进入开发者模式,打开show touches 和pointer locations勾上后,可以看到点击的轨迹,再结合adb shell sendevent输入以上消息,可以看到屏幕上出现点击效果。

实践证明我们是可以模拟的点击事件的,而且已经有现成的getevent 和 sendevent的方式可以很方便的使用。但是实际上,当我们使用这样的方式在Lenovo,Vivo的部分机型上验证的时候发现,getevent得到响应的事件输出的速度让人捉急,这中间产生的耗时对我们的UI测试来说其实很难忍受。

2.实践改造

基于getevent和setevent的原理,源码路径, 我们实现了一套可以从/dev/input/event*读取并写入的Kit,有兴趣的可以邮件联系我获得源码

备注:目前已经在MI 6,Lenovo zap,Vivo X21,HW nova4上验证通过。


参考
android跨进程事件注入——直接往linux底层写事件

Android getevent命令分析Input事件

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

推荐阅读更多精彩内容