前言
认真阅读了monkey程序的源码,没想到monkey程序除了支持从命令行直接执行外,还支持从特定的文件中读取【命令】执行,还可以从Socket中读取【命令】执行,当然这些【命令】得符合monkey程序的规范,这真是太牛逼了……monkey程序是2009年左右的代码,程序太稳了,几乎没有新的代码更新,如果你写过Android App,你会发现monkey程序与Android App截然不同,monkey程序是脱离Android App框架执行流的程序,每个Android App的主线程,也称作Ui线程,主线程涉及大量的GUI界面工作,monkey程序没有GUI界面,它是一个CLI程序,即命令行程序,它的主线程全部用来执行业务逻辑,这也是和带有界面的App程序的不同点!
在Android平台启动Java程序仍然脱离不了app_process这个c++程序,ART虚拟机是在app_process这个程序中启动的,所以monkey程序中也有Binder线程池的参与,它也能使用跨进程通信的Binder、也能使用Framework中的Java API,比如ActivityManger等等,这就是Android的标准。
今天将分析monkey程序支持的事件来源、以及各种事件的设计思想
先带着几个问题,继续我们今天的阅读
1、monkey程序支持哪些【事件来源】呢?
2、monkey程序又支持哪些【事件】呢?
3、不同的事件来源,包含的事件有什么区别?
这里注意事件来源与事件本身不是一回事,请继续向下阅读……
Monkey支持的4个事件来源
1、随机事件来源
解释:由命令行参数传递进去,我们日常使用monkey,一般使用的是这种
2、从单个脚本文件作为事件来源
解释:脚本文件路径由命令行参数传递到monkey中
3、从多个脚本文件中的随机选取其中一个脚本文件作为事件来源
解释:所有脚本文件的路径从命令行参数传递进去
4、从Socket端口中获取事件,Socket端口作为事件来源
解释:本机,监听在指定的端口中,此时的事件来源可以由其他进程写入到同一个端口中
Monkey事件来源的代码设计思想
概览:monkey程序的事件来源的面向对象设计上,共涉及到:1个接口类、4个具体的实现类
1个接口类规范了作为事件来源的基本要求(定下标准)
4个具体的实现类产生的对象,表示不同的4个事件来源
1、随机事件来源
2、单个脚本文件作为事件来源
3、多个脚本文件中的随机选取其中一个脚本文件作为事件来源
4、Socket端口作为事件来源
我们逐个分析1个接口类与4个具体类的设计思想。
以下图示说明了1个接口与4个具体类的关系!
无论哪种事件来源,都需要获取下一个事件、设置脚本详情、以及检查事件源是否有效,所以他们实现同一个接口,这个面向对象的功劳很大。
接口类介绍
1、MonkeyEventSource
MonkeyEventSource接口,表示作为事件来源应该具备哪些功能(能力),规范了3个功能(标准化)
getNextEvent():表示从当前事件源获取1个具体的事件
setVerbose(int):表示设置事件来源的日志等级【用于控制日志的输出】
validate():表示检查事件来源是否有效
该接口规范了作为事件来源,必须要有的功能,即获取事件、检查事件来源是否有效、以及日志控制
具体类介绍
1、MonkeySourceRandom
MoneySourceRandom实现了MonkeyEventSource接口,产生的对象表示一个具体的事件来源,我称它为随机事件来源,它也是我们平时使用monkey程序时的事件来源
2、MonkeySourceScript
MonkeySourceScript实现了MonkeyEventSource接口,在monkey程序命令行中指定选项参数-f xxxxFileFullPath时,此时创建的是MonkeySourceScript对象,我称它为单个脚本文件事件来源
该事件来源支持从单个脚本文件中读取定义好的事件,monkey程序规定了每一行作为【命令】的标准语法规则,这种方式好多人应该没用过,包括我,哈哈,以后可以尝试一下。
3、MonkeySourceRandomScript
MonkeySourceRandomScript实现了MonkeyEventSource接口,支持从多个脚本文件中随机选择一个脚本文件中的命令执行,我称它为多个脚本文件事件来源
在monkey程序的命令行中指定了多个选项参数-f xxxxFileFullPath -f xxxxFileFullPath,此时创建的是MonkeySrouceRandomScript对象
4、MonkeySourceNetwork
MonkeySourceNetwork实现了MonkeyEventSource接口,支持从Socket端口中读取命令,我称它为Socket事件来源
当在monkey的命令行中指定了选项参数--port xx端口号时,此时创建的是MonkeySourceNetwork对象作为事件来源
优先级情况(冲突)
monkey是CLI程序(命令行程序),当我们意外的在命令行中传入了多个以上的选项参数时,而参数又都与事件来源有关时,事件来源会按照优先级排列,产生冲突后,它们的优先级是:
脚本事件来源(单个或多个) > Socket事件来源 > 默认的随机事件来源
没想到吧,产生冲突后,我们最常用的事件来源,优先级反而是最低的!
Monkey事件的设计思想
概览:一个抽象类,16个子类,每个事件对象表示一个事件,在抽象类中定义了每个具体事件的通用属性以及行为,关系图如下:
1、MonkeyEvent
抽象类,定义(规范)了作为每种事件应该具备的属性,比如标记事件类型的eventType,以及定义了作为事件应该具备的功能(规范),还定义了一些事件分类用的常量值
MonkeyEvent():构造方法,强制规定创建每个MonkeyEvent对象时,必须赋值持有的eventType,即必须指定事件的类型
getEventType():用于获取当前事件的类型
isThrottlable():用于判断事件是否支持延迟处理,子类可重写
injectEvent():规范了实际执行事件的方法,明确说明最少需要依赖WMS系统服务、IMS系统服务(当然也可以不使用这两个系统服务)
2、MonkeyKeyEvent
表示实体【按键事件】的子类,每个对象代表一个实体按键事件,最终由InputManagerService系统服务注入事件
3、MonkeyTouchEvent
表示【触摸事件】的子类,每个对象代表触摸的动作,具体也是有IMS注入的事件
4、MonkeyTrackballEvent
表示【轨迹球事件】的子类,每个对象代表轨迹球动作(现在恐怕已经淘汰轨迹球了……),也是由IMS注入的事件
5、MonkeyRotationEvent
表示【屏幕旋转角度】的子类,每个对象代表一个旋转屏幕动作,具体由WindowManagerSerivce系统服务注入的事件
6、MonkeyActivityEvent
表示【启动Activity事件】的子类,每个对象代表启动Activity的动作,具体由AMS完成事件的注入,即启动Activity,只能启动根Activity(主Activity)
7、MonkeyFlipEvent
表示【键盘翻转的事件】的子类,每个对象代表键盘翻转动作,通过向设备结点文件/dev/input/event0,写入不同的值表示此事件
8、MonkeyThrottleEvent
表示【延迟执行的事件】的子类,每个对象代表一段延迟时间,延迟会造成monkey线程休眠,事件与事件之间的间隔时间也算做一个事件,这个设计的非常巧妙
9、MonkeyPermissionEvent
表示【权限检查的事件】的子类,每个对象代表一个权限检查事件
10、MonkeyNoopEvent
表示【什么也不做的事件】的子类,每个对象代表一个什么都不作的事件,这个事件只在Socket事件源中有所使用……一个哨兵事件
11、MonkeyPowerEvent
表示【SD卡写入日志的事件】的子类,每个对象代表向/sdcard/autotester.log文件中写入内容,这个事件只在单脚本来源中有所使用,即MonkeySourceScript时才会使用
同时它的事件类型竟然标记为:EVENT_TYPE_ACTIVITY……
12、MonkeyInstrumentationEvent
表示【启动与App框架之间的联动】的事件
同时它的事件类型竟然也标记为:EVENT_TYPE_ACTIVITY……
13、MonkeyGetFrameRateEvent
表示【获取帧率】的事件,同样只在MonkeySourceScript时才会使用
同时它的事件类型竟然也标记为:EVENT_TYPE_ACTIVITY……
14、MonkeyGetAppFrameRateEvent
获取【App帧】的事件?同样只在MonkeySourceScript时才会使用
同时它的事件类型竟然也标记为:EVENT_TYPE_ACTIVITY……
15、MonkeyMotionEvent(抽象类,抽象事件)封装几个通用的方法
16、MonkeyCommandEvent
执行一个【可执行文件(命令)】的事件,它也同样只在MonkeySourceScript时才会使用
同时它的事件类型竟然也标记为:EVENT_TYPE_ACTIVITY
17、MonkeyWaitEvent
表示停顿的事件,同样只在MonkeySourceScript时才会使用
总结
1、monkey程序支持4个事件来源,我们可以使用其中1种事件来源,只需要在命令行参数中指定即可,最常用的事件来源,是随机事件来源
随机事件来源
单个脚本文件事件来源
多个脚本文件事件来源
Socket事件来源
2、不同的事件来源,使用了不同的具体事件
3、专门一篇随机事件来源中,将总结它所使用的所有事件
4、下一篇我们分析monkey程序主执行流程,主要由一个Monkey类作为入口类,创建的Monkey对象又执行了哪些功能?以及Monkey对象又是如何使用事件来源以及调用事件来源中的每一个事件的……因为Monkey中涉及的功能较多,将分为多篇文章分解这些设计,所以下一篇将是入口类Monkey类加载的执行过程