从Monkey源码里学习几个adb shell命令和monekey日志的查阅方法
2015-07-31 09:29
1121 查看
一、昨天看了Monkey的代码,里边有几个adb shell的命令,记录一下。
1、procrank
2、cat /data/anr/traces.txt
抓取anr日志
3、dumpsys meminfo
查看内存详情
4、/data/tombstones
每当有native crash就会在这个目录下生成一个新文件,里边有native crash的堆栈及其他详细信息
要看native crash的堆栈我们也会用一下命令:
adb logcat | ndk-stack -sym navisdk/src/main/obj/local/armeabi
但这个要在crash发生前调用才生效。
5、这些命令是在android里通过代码执行的
二、从源码里看下monkey的日志打印机制
1、
以上是moneky处理anr异常的代码,因为打印开关是由mRequestAnrTraces和mRequestDumpsysMemInfo两个标志位控制的。另外出现anr的地方会马上打印procrank命令输出,可以通过在日志文件里搜索“NOT RESPONDING”来看是否有anr异常。
2、
3、native crash
4、下面就是monkey的不同类别动作会按到的一些按键,都定义在代码里
最下面的那个10个int类型变量就是对应monkey日志开头的那些百分比
1、procrank
2、cat /data/anr/traces.txt
抓取anr日志
3、dumpsys meminfo
查看内存详情
4、/data/tombstones
每当有native crash就会在这个目录下生成一个新文件,里边有native crash的堆栈及其他详细信息
要看native crash的堆栈我们也会用一下命令:
adb logcat | ndk-stack -sym navisdk/src/main/obj/local/armeabi
但这个要在crash发生前调用才生效。
5、这些命令是在android里通过代码执行的
/** * Print report from a single command line. * @param reportName Simple tag that will print before the report and in various annotations. * @param command Command line to execute. * TODO: Use ProcessBuilder & redirectErrorStream(true) to capture both streams (might be * important for some command lines) */ private void commandLineReport(String reportName, String command) { System.err.println(reportName + ":"); Runtime rt = Runtime.getRuntime(); try { // Process must be fully qualified here because android.os.Process is used elsewhere java.lang.Process p = Runtime.getRuntime().exec(command); // pipe everything from process stdout -> System.err InputStream inStream = p.getInputStream(); InputStreamReader inReader = new InputStreamReader(inStream); BufferedReader inBuffer = new BufferedReader(inReader); String s; while ((s = inBuffer.readLine()) != null) { System.err.println(s); } int status = p.waitFor(); System.err.println("// " + reportName + " status was " + status); } catch (Exception e) { System.err.println("// Exception from " + reportName + ":"); System.err.println(e.toString()); } }
二、从源码里看下monkey的日志打印机制
1、
public int appNotResponding(String processName, int pid, String processStats) { System.err.println("// NOT RESPONDING: " + processName + " (pid " + pid + ")"); System.err.println(processStats); reportProcRank(); synchronized (Monkey.this) { mRequestAnrTraces = true; mRequestDumpsysMemInfo = true; } if (!mIgnoreTimeouts) { synchronized (Monkey.this) { mAbort = true; } return (mKillProcessAfterError) ? -1 : 1; } return 1; }
以上是moneky处理anr异常的代码,因为打印开关是由mRequestAnrTraces和mRequestDumpsysMemInfo两个标志位控制的。另外出现anr的地方会马上打印procrank命令输出,可以通过在日志文件里搜索“NOT RESPONDING”来看是否有anr异常。
2、
public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg, byte[] crashData) { System.err.println("// CRASH: " + processName + " (pid " + pid + ")"); System.err.println("// Short Msg: " + shortMsg); System.err.println("// Long Msg: " + longMsg); if (crashData != null) { try { CrashData cd = new CrashData(new DataInputStream( new ByteArrayInputStream(crashData))); System.err.println("// Build Label: " + cd.getBuildData().getFingerprint()); System.err.println("// Build Changelist: " + cd.getBuildData().getIncrementalVersion()); System.err.println("// Build Time: " + cd.getBuildData().getTime()); System.err.println("// ID: " + cd.getId()); System.err.println("// Tag: " + cd.getActivity()); System.err.println(cd.getThrowableData().toString( "// ")); } catch (IOException e) { System.err.println("// BAD STACK CRAWL"); } } if (!mIgnoreCrashes) { synchronized (Monkey.this) { mAbort = true; } return !mKillProcessAfterError; } return false; }如果设置了--ignore-crashes,mIgnoreCrashes会置为true,crash会在moneky日志中打印,但不会停止发送事件,要搜crash日志可以搜索“CRASH”关键字(见以上代码),要注意此时moneky日志结束处没有crash的提示。
3、native crash
private int runMonkeyCycles() { int i = 0; int lastKey = 0; boolean systemCrashed = false; while (!systemCrashed && i < mCount) { synchronized (this) { if (mRequestAnrTraces) { reportAnrTraces(); mRequestAnrTraces = false; } if (mRequestDumpsysMemInfo) { reportDumpsysMemInfo(); mRequestDumpsysMemInfo = false; } if (mMonitorNativeCrashes) { // first time through, when i == 0, just set up the watcher (ignore the error) if (checkNativeCrashes() && (i > 0)) { System.out.println("** New native crash detected."); mAbort = mAbort || mKillProcessAfterError; } } if (mAbort) { System.out.println("** Monkey aborted due to error."); System.out.println("Events injected: " + i); return i; } }主循环中每次发出一系列事件前会检查,如果上次的一系列事件出现了anr,会再下一系列事件发送前打印traces.txt和执行dumpsys meminfo,同时把标志位复位。另外如果监听native crash,会打印"** New native crash detected.",事后要知道是具体什么原因的话,只能自己去查/data/tombstones目录了。
4、下面就是monkey的不同类别动作会按到的一些按键,都定义在代码里
/** Key events that move around the UI. */ private static final int[] N***_KEYS = { KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT, }; /** * Key events that perform major navigation options (so shouldn't be sent * as much). */ private static final int[] MAJOR_N***_KEYS = { KeyEvent.KEYCODE_MENU, /*KeyEvent.KEYCODE_SOFT_RIGHT,*/ KeyEvent.KEYCODE_DPAD_CENTER, }; /** Key events that perform system operations. */ private static final int[] SYS_KEYS = { KeyEvent.KEYCODE_HOME, KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_CALL, KeyEvent.KEYCODE_ENDCALL, KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_MUTE, }; /** Nice names for all key events. */ private static final String[] KEY_NAMES = { "KEYCODE_UNKNOWN", "KEYCODE_MENU", "KEYCODE_SOFT_RIGHT", "KEYCODE_HOME", "KEYCODE_BACK", "KEYCODE_CALL", "KEYCODE_ENDCALL", "KEYCODE_0", "KEYCODE_1", "KEYCODE_2", "KEYCODE_3", "KEYCODE_4", "KEYCODE_5", "KEYCODE_6", "KEYCODE_7", "KEYCODE_8", "KEYCODE_9", "KEYCODE_STAR", "KEYCODE_POUND", "KEYCODE_DPAD_UP", "KEYCODE_DPAD_DOWN", "KEYCODE_DPAD_LEFT", "KEYCODE_DPAD_RIGHT", "KEYCODE_DPAD_CENTER", "KEYCODE_VOLUME_UP", "KEYCODE_VOLUME_DOWN", "KEYCODE_POWER", "KEYCODE_CAMERA", "KEYCODE_CLEAR", "KEYCODE_A", "KEYCODE_B", "KEYCODE_C", "KEYCODE_D", "KEYCODE_E", "KEYCODE_F", "KEYCODE_G", "KEYCODE_H", "KEYCODE_I", "KEYCODE_J", "KEYCODE_K", "KEYCODE_L", "KEYCODE_M", "KEYCODE_N", "KEYCODE_O", "KEYCODE_P", "KEYCODE_Q", "KEYCODE_R", "KEYCODE_S", "KEYCODE_T", "KEYCODE_U", "KEYCODE_V", "KEYCODE_W", "KEYCODE_X", "KEYCODE_Y", "KEYCODE_Z", "KEYCODE_COMMA", "KEYCODE_PERIOD", "KEYCODE_ALT_LEFT", "KEYCODE_ALT_RIGHT", "KEYCODE_SHIFT_LEFT", "KEYCODE_SHIFT_RIGHT", "KEYCODE_TAB", "KEYCODE_SPACE", "KEYCODE_SYM", "KEYCODE_EXPLORER", "KEYCODE_ENVELOPE", "KEYCODE_ENTER", "KEYCODE_DEL", "KEYCODE_GR***E", "KEYCODE_MINUS", "KEYCODE_EQUALS", "KEYCODE_LEFT_BRACKET", "KEYCODE_RIGHT_BRACKET", "KEYCODE_BACKSLASH", "KEYCODE_SEMICOLON", "KEYCODE_APOSTROPHE", "KEYCODE_SLASH", "KEYCODE_AT", "KEYCODE_NUM", "KEYCODE_HEADSETHOOK", "KEYCODE_FOCUS", "KEYCODE_PLUS", "KEYCODE_MENU", "KEYCODE_NOTIFICATION", "KEYCODE_SEARCH", "KEYCODE_PLAYPAUSE", "KEYCODE_STOP", "KEYCODE_NEXTSONG", "KEYCODE_PREVIOUSSONG", "KEYCODE_REWIND", "KEYCODE_FORWARD", "KEYCODE_MUTE", //BORQS_EXT "KEYCODE_MOBILETV", "KEYCODE_LANGUAGE", "KEYCODE_VOICE_RECOGNIZER", "KEYCODE_CUSTOMER", //END "TAG_LAST_KEYCODE" // EOL. used to keep the lists in sync }; public static final int FACTOR_TOUCH = 0; public static final int FACTOR_MOTION = 1; public static final int FACTOR_TRACKBALL = 2; public static final int FACTOR_N*** = 3; public static final int FACTOR_MAJORN*** = 4; public static final int FACTOR_SYSOPS = 5; public static final int FACTOR_APPSWITCH = 6; public static final int FACTOR_FLIP = 7; public static final int FACTOR_ANYTHING = 8; public static final int FACTORZ_COUNT = 9; // should be last+1
最下面的那个10个int类型变量就是对应monkey日志开头的那些百分比
// Event percentages: // 0: 55.0% // 1: 45.0% // 2: 0.0% // 3: -0.0% // 4: -0.0% // 5: -0.0% // 6: -0.0% // 7: -0.0% // 8: -0.0% // 9: 0.0% // 10: -0.0%
相关文章推荐
- 简单myshell的实现
- shell 交互
- linux shell man命令详细介绍-快捷获得帮助信息(2)
- shell脚本
- 【Linux】Shell中的正则表达式
- linux shell命令快捷获得系统帮助(一)[man-pages定义规范]
- 【Powershell】【 数组】脚本示例一则
- 编写shell管理脚本(二)
- 编写shell管理脚本(一)
- 通过shell登录OSC并备份博文
- shell脚本例子集锦(习题总结)
- Linux的shell中echo改变输出显示样式
- spark shell学习笔记
- linux中查看现在使用的shell是ksh还是bash?以及怎样修改?
- linux中查看现在使用的shell是ksh还是bash?以及怎样修改?
- 基于sparksql调用shell脚本执行SQL
- 写过的一些shell脚本总结
- 由Java代码运行shell命令/脚本
- 使用ShellExecute打开文件夹并选中文件
- shell 获取指定日期的前N天或后N天