Monkey源代码分析之执行流程
在《MonkeyRunner源代码分析之与Android设备通讯方式》中。我们谈及到MonkeyRunner控制目标android设备有多种方法。当中之中的一个就是在目标机器启动一个monkey服务来监听指定的一个port,然后monkeyrunner再连接上这个port来发送命令。驱动monkey去完毕对应的工作。
当时我们仅仅分析了monkeyrunner这个client的代码是怎么实现这一点的,但没有谈monkey那边是怎样接受命令,接受到命令又是怎样处理的。
所以自己打开源代码看了一个晚上,大概有了概念。但今天网上搜索了下。发现已经有网友“chenjie”对monkey的源代码做过对应的分析了,并且文章写得很有概括性。应该是高手所为,果断花了2个积分下载下来。不敢独享。本想贴上来分享给大家。但发现pdf的文档直接拷贝上来会丢失掉图片,所以仅仅好贴上下载地址:http://download.csdn.net/download/zqilu/6884491
但文章主要是架构性得去描写叙述monkey是怎么工作的,依照我自己的习惯。我还是喜欢依照自己的思维和有目的性的去了解我想要的。在这里我想要的是搞清楚monkey是怎样处理monkeyrunner过来的命令的。
本文我们就先看下monkey的执行流程。
1. 执行环境设置
和monkeyrunner一样。monkey这个命令也是一个shell脚本。它是在我们的目标android设备的“/system/bin/monkey”,事实上这是一个android上面java程序启动的标准流程。
base=/system
export CLASSPATH=$base/framework/monkey.jar
trap "" HUP
exec app_process $base/bin com.android.commands.monkey.Monkey $*
android中能够通过多种方式启动java应用,通过app_process命令启动就是当中一种。它能够帮忙注冊android JNI,而绕过dalvik以使用Native API(如我般不清楚的请百度)所做的主要事情例如以下:
- 设置monkey的CLASSPATH环境变量指向monkey.jar
- 通过app_process指定monkey的入口和传进来的全部參数启动上面CLASSPATH设定的monkey.jar
2.命令行參数解析
/**
* Command-line entry point.
*
* @param args The command-line arguments
*/
public static void main(String[] args) {
// Set the process name showing in "ps" or "top"
Process.setArgV0("com.android.commands.monkey"); int resultCode = (new Monkey()).run(args);
System.exit(resultCode);
}
- 处理命令行參数
- 依据命令行參数启动不同的事件源,也就是我们的測试事件到底是从网络如monkeyrunner过来的还是monkey内部的random測试数据集过来的还是脚本过来的如此之类
- 跳入runMonkeyCyncle方法针对不同的事件源開始获取并运行不同的事件
private int run(String[] args) {
...
if (!processOptions()) {
return -1;
}
...
}
进去之后就是非常普通的读取命令行的參数然后一个个进行解析保存了,没有太多特别的东西,这里就直接贴出monkey的參数选项大家看看就好了:
3. 初始化測试事件源
private int run(String[] args) {
...
if (mScriptFileNames != null && mScriptFileNames.size() == 1) {
// script mode, ignore other options
mEventSource = new MonkeySourceScript(mRandom, mScriptFileNames.get(0), mThrottle,
mRandomizeThrottle, mProfileWaitTime, mDeviceSleepTime);
mEventSource.setVerbose(mVerbose);
mCountEvents = false;
} else if (mScriptFileNames != null && mScriptFileNames.size() > 1) {
if (mSetupFileName != null) {
mEventSource = new MonkeySourceRandomScript(mSetupFileName,
mScriptFileNames, mThrottle, mRandomizeThrottle, mRandom,
mProfileWaitTime, mDeviceSleepTime, mRandomizeScript);
mCount++;
} else {
mEventSource = new MonkeySourceRandomScript(mScriptFileNames,
mThrottle, mRandomizeThrottle, mRandom,
mProfileWaitTime, mDeviceSleepTime, mRandomizeScript);
}
mEventSource.setVerbose(mVerbose);
mCountEvents = false;
} else if (mServerPort != -1) {
try {
mEventSource = new MonkeySourceNetwork(mServerPort);
} catch (IOException e) {
System.out.println("Error binding to network socket.");
return -5;
}
mCount = Integer.MAX_VALUE;
} else {
// random source by default
if (mVerbose >= 2) { // check seeding performance
System.out.println("// Seeded: " + mSeed);
}
mEventSource = new MonkeySourceRandom(mRandom, mMainApps, mThrottle, mRandomizeThrottle);
mEventSource.setVerbose(mVerbose);
// set any of the factors that has been set
for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) {
if (mFactors[i] <= 0.0f) {
((MonkeySourceRandom) mEventSource).setFactors(i, mFactors[i]);
}
}
// in random mode, we start with a random activity
((MonkeySourceRandom) mEventSource).generateActivity();
}
...
mNetworkMonitor.start();
int crashedAtCycle = runMonkeyCycles();
mNetworkMonitor.stop();
...
}
事件源代表測试数据的事件是从哪里过来的。不同的event source会有不同的类来做对应的实现:
- MonkeySourceNetwork.java: 事件是从网络如monkeyrunner过来的,处理的是《MonkeyRunner源代码分析之与Android设备通讯方式》描写叙述的界面控制操作事件
- MonkeySourceNetworkVars.java: 事件也是从网络如monkeyrunner过来的,处理的是《MonkeyRunner源代码分析之与Android设备通讯方式》提到的getPropery事件
- MonkeySourceNetworkViews.java:事件也是从网络如monkeyrunner过来的。处理的是《MonkeyRunner源代码分析之与Android设备通讯方式》提到的Views相关的事件
- MonkeySourceRandom.java:事件是从monkey内部生成的随机事件集,也就是我们通过命令行启动monkey測试目标app的经常使用方式
- MonkeySourceRanodomeScript.java: 上面的随机内部数据源也能够通过指定setup脚本来创建
- MonkeySourceScript.java: 用户也能够遵循一定的规则编写monkey脚本来驱动monkey进行相关測试。与上面不同的是它不再是随机的
- 从指定的源获取命令
- 把命令翻译成monkey事件然后放到命令队列EventQueue
这些都是面向对象的面向接口编程的基础了。大家有不清楚的最好先去了解下java的一些基本知识。这样理解起来会快非常多。
4. 循环运行事件
private int run(String[] args) {
...
int crashedAtCycle = runMonkeyCycles();
...
}
如前所述,runMonkeyCyles方法会依据不同的数据源開始一条条的获取事件并进行运行:
/**
* Run mCount cycles and see if we hit any crashers.
* <p>
* TODO: Meta state on keys
*
* @return Returns the last cycle which executed. If the value == mCount, no
* errors detected.
*/
private int runMonkeyCycles() {
int eventCounter = 0;
int cycleCounter = 0; boolean shouldReportAnrTraces = false;
boolean shouldReportDumpsysMemInfo = false;
boolean shouldAbort = false;
boolean systemCrashed = false; // TO DO : The count should apply to each of the script file.
while (!systemCrashed && cycleCounter < mCount) {
...
MonkeyEvent ev = mEventSource.getNextEvent();
if (ev != null) {
int injectCode = ev.injectEvent(mWm, mAm, mVerbose);
...
}
...
}
....
}
注意这里的mEventSource就是我们上面提到的事件源的接口。它屏蔽了每一个事件实现类的详细细节,我们仅仅须要告诉这个接口我们如今须要取一条事件然后运行它。该结构依据面向对象的多态原理,就会自己主动取事件的实现类获得相应的事件进行返回。
本人曾经做过开发。所以还ok。
这里仅仅是做一个善意的提醒。
|
作者 |
自主博客 |
微信 |
CSDN |
|
天地会珠海分舵 |
服务号:TechGoGoGo 扫描码: |
http://blog.csdn.net/zhubaitian |
Monkey源代码分析之执行流程的更多相关文章
- Monkey源代码分析之事件源
上一篇文章<Monkey源代码分析之执行流程>给出了monkey执行的整个流程.让我们有一个概貌,那么往后的文章我们会尝试进一步的阐述相关的一些知识点. 这里先把整个monkey类的结构图 ...
- Monkey源代码分析之事件注入
本系列的上一篇文章<Monkey源代码分析之事件源>中我们描写叙述了monkey是怎么从事件源取得命令.然后将命令转换成事件放到事件队列里面的.可是到如今位置我们还没有了解monkey里面 ...
- openVswitch(OVS)源代码分析之工作流程(数据包处理)
上篇分析到数据包的收发,这篇开始着手分析数据包的处理问题.在openVswitch中数据包的处理是其核心技术,该技术分为三部分来实现:第一.根据skb数据包提取相关信息封装成key值:第二.根据提取到 ...
- Monkey源代码分析番外篇之Android注入事件的三种方法比較
原文:http://www.pocketmagic.net/2012/04/injecting-events-programatically-on-android/#.VEoIoIuUcaV 往下分析 ...
- monkey源代码分析之事件注入方法变化
在上一篇文章<Monkey源代码分析之事件注入>中.我们看到了monkey在注入事件的时候用到了<Monkey源代码分析番外篇之Android注入事件的三种方法比較>中的第一种 ...
- openVswitch(OVS)源代码分析之工作流程(flow流表查询)
原文链接: openVswitch(OVS)源代码分析之工作流程(flow流表查询)
- [gevent源代码分析] 深度分析gevent执行流程
一直对gevent执行流程比較模糊,近期看源代码略有所得.不敢独享.故分享之. gevent是一个高性能网络库,底层是libevent,1.0版本号之后是libev.核心是greenlet.geven ...
- Spark SQL源代码分析之核心流程
/** Spark SQL源代码分析系列文章*/ 自从去年Spark Submit 2013 Michael Armbrust分享了他的Catalyst,到至今1年多了,Spark SQL的贡献者从几 ...
- Monkey源代码分析番外篇WindowManager如何出的喷射事件的进程间的安全限制
在分析monkey源代码时的一些背景知识不明确,例如看到monkey它是用windowmanager的injectKeyEvent的喷射事件时的方法.我发现自己陷入疙瘩,这种方法不仅能够在当前的应用程 ...
随机推荐
- netduino第一步,环境配置
在netduino.com的官网介绍下,我很快就入门,现在的最新netduino的版本是4.3,但4.3是运行在win8下的,在codeplex.net上有,大部分人还使用的是win7,因此我现在采用 ...
- SQL Select语句完整的执行顺序
1.from子句组装来自不同数据源的数据: 2.where子句基于指定的条件对记录行进行筛选: 3.group by子句将数据划分为多个分组: 4.使用聚集函数进行计算: 5. 使用having子句筛 ...
- [置顶] ARM-Linux下WEB服务器Boa的移植、配置和运行测试
Linux下使用的轻量级WEB服务器主要有:lighttpd.thttpd.shttpd和boa等等,而Boa是使用最为广泛的轻量级WEB服务器之一(当然,阿帕奇是世界使用排名第一的Web服务器软件) ...
- vim 操作指令1
1.vim 在命令行中输入vim,进入vim编辑器 2.i 按一下i键,下端显示 –INSERT–插入命令,在vim中可能任意字符都有作用 3.Esc 退出i(插入)命令进行其它命令使用 4.:r f ...
- Jenkins: 使用Jenkins搭建持续集成(CI)环境
http://www.cnitblog.com/luckydmz/archive/2012/01/03/77007.html 首先从官网http://jenkins-ci.org/下载 Java We ...
- 联系人数据库设计之AbstractContactsProvider
个人见解,欢迎交流. 联系人数据库设计,源代码下载请自行去android官网下载. package com.android.providers.contacts; import android.con ...
- WM_ERASEBKGND官方解释(翻译),以及Delphi里所有的使用情况(就是绘制窗口控件背景色,并阻止进一步传递消息)
#define WM_ERASEBKGND 0x0014 Parameters wParam A handle to the device context. // ...
- html中的rowspan和colspan
摘自w3school(http://www.w3school.com.cn/tags/att_td_colspan.asp)colspan 属性规定单元格可横跨的列数.<table border ...
- 14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚 如果自动提交模式被启用,在InnoDB里, 所有的用户活动发生在一个事务里, 每个SQL语句 ...
- Java中替代C# ref/out 关键字方案:
刚学习Java不久,今天遇到一个问题,需要在方法中修改传入的对象的值,确切的说是需要使用一个方法,创建一个对象,并把其引用返回,熟悉C#的我的第一反应就是C#中的ref/out关键字,结果发现Java ...