Monkey源码获取:https://android.googlesource.com/platform/development.git/
monkey,一个Android平台的命令行工具,既熟悉又陌生,熟悉的是很多同学一定使用过monkey,而陌生的是对它的原理完全不懂,所以才有今天学习Monkey的源码设计,它是如何实现的呢?
monkey源码下载地址:https://github.com/aosp-mirror/platform_development/tree/master/cmds/monkey
Google:https://android.googlesource.com/platform/development.git/+/refs/heads/master/cmds/monkey/src/com/android/commands/monkey
adb shell type monkey monkey is a tracked alias for /system/bin/monkey
Android基于Linux内核,所以它也有内置的type命令(type命令是一个可执行文件,它可以用于查看可执行文件的类型), 当我们执行adb shell type monkey,可以看到屏幕中的这么一行:monkey is a tracked alias for /system/bin/monkey,这句话的意思是monkey是/system/bin/monkey这个可执行文件的别称,当我们输入adb shell monkey的时候,执行的可执行文件是位于Android系统中的/system/bin/monkey可执行文件,接下来学习/system/bin/monkey这个文本文件的内容都是些什么呢?
# Script to start "monkey" on the device, which has a very rudimentary # shell. # base=/system export CLASSPATH=$base/framework/monkey.jar trap "" HUP for a in "$@"; do echo " bash arg:" $a done exec app_process $base/bin com.android.commands.monkey.Monkey "$@"
它是monkey的可执行文件,位于/system/bin目录下的一个shell脚本文件,接下来一起分析这个shell脚本
1、创建全局变量base,用于存储目录名称
创建一个称为base的全局变量,变量值是/system,可见存储的是一个路径
2、导出环境变量值,用于记录monkey.jar文件的绝对路径
使用export命令,导出一个环境变量CLASSPATH,环境变量值是$base/framework/monkey.jar,shell脚本会先做变量值替换,$base会被替换,最终的变量值是/system/framework/monkey.jar
monkey.jar就是monkey项目的字节码jar包,里面都是.class字节码文件,可见monkey程序是Java写的……(are you sure?难道不是dex?)
3、捕获HUB信号,然后处理
trap命令用于捕获信号,然后处理,HUP:HUP中断信号表示用户键入<Ctrl+X>时由终端驱动程序发送的信号,中间""表示捕获到信号后做的事情,这里表示捕获到HUP信号后什么也没有做!
4、循环所有参数,在屏幕中打印出来……
一行一个的打印,这是shell循环的语法,echo命令用于向屏幕中输出内容,$@则可以获取所有的命令行参数,就是我们给monkey命令传入的参数
5、替换程序,可执行文件app_process开始运行
exec命令用于在当前shell进程中替换程序。这里会替换一个新的程序运行,因此处最初为一个shell进程,接着shell进程中执行的程序替换为app_process(当前的shell程序会被替换,改为执行app_process的程序的代码逻辑),$bash/bin和com.android.commands.monkey.Monkey、还有"$@"解析出来的所有命令行参数,会全部作为app_process程序(可执行文件)的参数传给app_process……,而app_process是一个可执行文件,它是由c++编写的,它因为会创建虚拟机实例,所以可以用来执行Java程序!
一个可执行文件,由c++编写,它也是zygote进程中运行的程序,在app_process程序中会创建虚拟机实例,由于app_process涉及内容较多,第一篇点到为止,后面专门写一篇app_process的分析,这里可知道monkey程序的主要逻辑还是在monkey.jar包中的字节码文件中,app_process程序会读取CLASSPATH环境变量的值,由于其指向的是CLASSPATH=$base/framework/monkey.jar,所以app_process程序可以找到称为com.android.commands.monkey.Monkey类,这样就可以加载这个Monkey类到ART虚拟机中执行Java程序了!
adb shell monkey -p your.package.name -v 500
执行monkey命令,4个命令行参数全部传入到monkey脚本中,以下是shell解释器替换后的monkey启动脚本(shell解释器做的,实际你是看不到的,这里用于辅助理解monkey)
# Script to start "monkey" on the device, which has a very rudimentary # shell. # base=/system export CLASSPATH=/system/framework/monkey.jar trap "" HUP for a in -p your.package.name -v 500; do echo " bash arg:" $a done exec app_process $base/bin com.android.commands.monkey.Monkey -p your.package.name -v 500
1、这一句com.android.commands.monkey.Monkey,让我们知道这是java程序的入口类,就是Monkey类,它的静态方法main()一定会执行,而Monkey类后面的就是命令行参数,比如上文中提及的传入的几个参数
2、接下来的第二篇文章中,将分析Monkey类的静态方法main()做了那些事情,静态方法main()是monkey程序的入口,monkey的主线程(进程)将在此运行