【Android稳定性测试】Monkey源码分析(一):源码下载及主结构简介

569 阅读5分钟

1.Android源码下载

  Monkey的编译依赖于Android源码,所以后续若要二次开发需要下载完整AOSP;
下载参考文档 source.android.google.cn/source/down…
相关命令在不同系统,可能会遇到一些问题,下面整理了博主的下载过程及遇到的个别问题。

  • 系统:Mac
  • python版本:3.9.7

1.1 安装repo

  • Repo是谷歌开发的用于管理Android版本库的工具,使用python对git进行了一些封装,
    简化对各个git版本库的管理;
  • Android源码引用了很多开源的项目,每个项目又是一个独立的git仓库、每个仓库又有不同的分支版本,为了方便统一管理,开发了Repo在上层进行批量处理。
## 确保有bin目录,并使目录包含在PATH中
mkdir ~/bin
PATH=~/bin:$PATH
## 下载Repo工具,并确保它可执行
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

    下载成功后 /bin 目录下会有repo脚本出现;     image.png

1.2 初始化repo

## 本地新建一个文件夹,用于存放要下载的代码
mkdir android6
cd android6
## 初始化,这里要下载Android6,使用-b参数指定,可按需选择你要的Android版本
## 已有版本号可参考:https://source.android.com/docs/setup/about/build-numbers
repo init -u https://android.googlesource.com/platform/manifest -b android-6.0.1_r81
  • 此时可能会遇到python版本报错;     image.png
##因为mac或ubuntu默认使用python2.x,repo脚本当前应该是python3.x
##可以指定下python版本去执行repo命令
sudo python3 ~/bin/repo init -u https://android.googlesource.com/platform/manifest -b android-6.0.1_r81
  • 还可能会遇到证书报错,是python打开https缺少本地证书的问题;
##终端证书报错信息
fatal: Cannot get https://gerrit.googlesource.com/git-repo/clone.bundle
fatal: error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)
fatal: double check your --repo-rev setting.
fatal: cloning the git-repo repository failed, will remove '.repo/repo'
##解决方法: 下载证书放到指定文件夹下即可
##可以先在/bin/repo脚本中添加打印查看默认证书位置的代码,在终端可看到相关log输出
import ssl
print(ssl.get_default_verify_paths())

##再次执行上面的repo init命令,应可看到如下结果,证书文件返回结果是None、表示无证书
DefaultVerifyPaths(cafile=None, capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/Library/Frameworks/Python.framework/Versions/3.9/etc/openssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/Library/Frameworks/Python.framework/Versions/3.9/etc/openssl/certs')
##可以看到打印出了证书的默认路径,下载证书并放到默认路径中即可解决该问题
##证书下载地址 http://curl.haxx.se/ca/cacert.pem

##然后根据openssl_capath返回的路径新建certs文件夹,
##并将刚刚下载的证书移动过去、同时命名为openssl_cafile返回结果中的cert.pem
cd /Library/Frameworks/Python.framework/Versions/3.9/etc/openssl 
mkdir certs 
mv ~/Downloads/cacert.pem ./ 
mv cacert.pem cert.pem

##解决问题后,记得切回android6文件夹
cd android6
##此时再次执行上面的repo init命令应可看到打印的证书信息不再为空,且命令可执行成功
DefaultVerifyPaths(cafile='/Library/Frameworks/Python.framework/Versions/3.9/etc/openssl/cert.pem', capath='/Library/Frameworks/Python.framework/Versions/3.9/etc/openssl/certs', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/Library/Frameworks/Python.framework/Versions/3.9/etc/openssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/Library/Frameworks/Python.framework/Versions/3.9/etc/openssl/certs')


1.3 下载Android源码树

repo sync
或
sudo python3 ~/bin/repo sync
##下载时间较长(7h+),可以夜间执行

   下载成功有提示   image.png

2.Monkey源码简介

2.1 代码路径

android6/development/cmds/monkey/src/com/android/commands/monkey

##package com.android.commands.monkey
##主类:Monkey.java

2.2 代码主要结构

  • Monkey.java
    文件中的main()方法是Monkey执行的主入口;

  • 事件来源
    Monkey一共设置了四种事件来源方式,我们常用的就是从命令行传递参数开启随机事件测试;

    • 随机事件来源:由命令行参数传递(最常使用的方式)
      会先判断是否是其它三种来源,不是则使用该事件来源
    • 单个脚本文件作为事件来源:以预设置的脚本文件作为事件来源
      对应Monkey执行参数中的-f scriptfile
    • 多脚本中随机选择一个作为来源:和上一个类似,如果添加多个-f,会随机选择一个脚本执行
      对应执行参数-f scriptfile [-f scriptfile]
    • socket端口获取事件:从socket端口中获取事件,此时事件来源可以由其它程序写入一个端口
      对应执行参数--port port(很少使用)

      Monkey的四种来源统一实现了MonkeyEventSource接口,大体结构如下:
    image.png

  • 事件类
    Monkey将模拟用户操作的各类型事件分成了十几大类,然后统一继承MonkeyEvent超类,
    源码大体结构如下图:

image.png

MonkeyActivityEvent.java
启动Activity事件
用于模拟用户在应用程序中切换或启动活动的行为
根据指定的组件名启动活动,并提供了一些错误处理逻辑

MonkeyCommandEvent.java
shell命令事件
根据指定的shell命令执行操作,并提供了一些错误处理逻辑

MonkeyFlipEvent.java
monkey keyboard flip event 代码注释给的是键盘翻转事件
将模拟键盘翻转事件写入到 "/dev/input/event0" 文件中
对应Monkey执行参数--pct-flip
目前测试很少使用了,若配置了该参数,一般会报权限错误
“Got IOException performing flipjava.io.IOException: write failed: EINVAL(Invalid argument)
// Injection Failed”

MonkeyGetAppFrameRateEvent.java
用于捕获给定应用程序的帧率,它通过执行shell命令"dumpsys gfxinfo"来获取应用程序的帧率信息,
并计算平均帧率,然后将结果写入SD卡上的文件

MonkeyGetFrameRateEvent.java
通过调用SurfaceFlinger服务来获取帧率信息,并将结果写入文件

MonkeyInstrumentationEvent.java
应该是调用的Instrumentation测试框架,该事件要配合测试脚本使用 (很少使用)

MonkeyKeyEvent.java
模拟按键事件
对应执行参数
--pct-nav、--pct-majornav、--pct-syskeys、--pct-anyevent

MonkeyMotionEvent.java
模拟移动事件的抽象类

MonkeyTrackballEvent.java
滚动事件
对应执行参数--pct-trackball

MonkeyTouchEvent.java
触摸事件
对应执行参数 --pct-touch、--pct-motion、--pct-pinchzoom

MonkeyRotationEvent.java
屏幕旋转事件
对应执行参数 --pct-rotation

MonkeyThrottleEvent.java
事件间添加等待间隔,也被看做一个单独的事件
对应执行参数[--throttle MILLISEC]

MonkeyWaitEvent.java
添加等待事件
对应参数[--profile-wait MILLISEC]
代码中有注释,是脚本调起的模式下使用的,This is for the scripted monkey

MonkeyNoopEvent.java
空操作事件
只在Socket事件源中有所使用

MonkeyPowerEvent.java
写入日志事件
向/sdcard/autotester.log文件中写入内容,这个事件只在单脚本来源中有所使用

MonkeyPermissionEvent.java
权限检测事件
对应执行参数 [--pct-permission PERCENT]

总结
可以看到很多类是服务于脚本事件来源启动方式的,不太常用,
二次开发中我们重点关注随机事件来源常用的事件类即可,
后续博主会继续整理下main主方法的工作流程、以及常用事件类的详细实现。