您的位置:首页 > 运维架构 > Shell

从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里通过代码执行的

/**
     * 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%
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: