Android测试之Monkey原理及源码分析(五)

monkey.java::run()第五部分源码——monkey不同运行过程
monkey有4种不同的处理情况:MonkeySourceScript(),MonkeySourceRandomScript(),MonkeySourceNetwork(),MonkeySourceRandom(),接下来我们具体来看一下这4个都是如何处理的。
1.MonkeySourceScript()——脚本运行

        mRandom = new Random(mSeed);

        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;
        }

1)如果monkey参数包含“-f”且只有一个脚本,则通过MonkeySourceScript()直接运行该脚本。
2)MonkeySourceScript()对于脚本的处理,就是获取随机数、脚本名、固定延迟、随机延迟、等待时间、休眠时间,然后将随机数、固定延迟、随机延迟传给MonkeyEventQueue加入monkey事件队列。
MonkeySourceScript.java::MonkeySourceScript()

    public MonkeySourceScript(Random random, String filename, long throttle,
            boolean randomizeThrottle, long profileWaitTime, long deviceSleepTime) {
        mScriptFileName = filename;
        mQ = new MonkeyEventQueue(random, throttle, randomizeThrottle);
        mProfileWaitTime = profileWaitTime;
        mDeviceSleepTime = deviceSleepTime;
    }

在MonkeySourceScript.java中我们也可以看到event key word,这对应于前面提到的事件:

    private static final String EVENT_KEYWORD_POINTER = "DispatchPointer";
    private static final String EVENT_KEYWORD_TRACKBALL = "DispatchTrackball";
    private static final String EVENT_KEYWORD_ROTATION = "RotateScreen";
    private static final String EVENT_KEYWORD_KEY = "DispatchKey";
    private static final String EVENT_KEYWORD_FLIP = "DispatchFlip";
    private static final String EVENT_KEYWORD_KEYPRESS = "DispatchPress";
    private static final String EVENT_KEYWORD_ACTIVITY = "LaunchActivity";
    private static final String EVENT_KEYWORD_INSTRUMENTATION = "LaunchInstrumentation";
    private static final String EVENT_KEYWORD_WAIT = "UserWait";
    private static final String EVENT_KEYWORD_LONGPRESS = "LongPress";
    private static final String EVENT_KEYWORD_POWERLOG = "PowerLog";
    private static final String EVENT_KEYWORD_WRITEPOWERLOG = "WriteLog";
    private static final String EVENT_KEYWORD_RUNCMD = "RunCmd";
    private static final String EVENT_KEYWORD_TAP = "Tap";
    private static final String EVENT_KEYWORD_PROFILE_WAIT = "ProfileWait";
    private static final String EVENT_KEYWORD_DEVICE_WAKEUP = "DeviceWakeUp";
    private static final String EVENT_KEYWORD_INPUT_STRING = "DispatchString";
    private static final String EVENT_KEYWORD_PRESSANDHOLD = "PressAndHold";
    private static final String EVENT_KEYWORD_DRAG = "Drag";
    private static final String EVENT_KEYWORD_PINCH_ZOOM = "PinchZoom";
    private static final String EVENT_KEYWORD_START_FRAMERATE_CAPTURE = "StartCaptureFramerate";
    private static final String EVENT_KEYWORD_END_FRAMERATE_CAPTURE = "EndCaptureFramerate";
    private static final String EVENT_KEYWORD_START_APP_FRAMERATE_CAPTURE =
            "StartCaptureAppFramerate";
    private static final String EVENT_KEYWORD_END_APP_FRAMERATE_CAPTURE = "EndCaptureAppFramerate";

2.MonkeySourceRandomScript()——随机脚本运行

 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;
        }

如果monkey参数包含“-f”但不止一个脚本,则通过MonkeySourceRandomScript()随机运行这些脚本,这里需要注意monkey参数中是否包含“–setup”:
1)若包含,则先运行带“–setup”的脚本,再随机运行其余脚本。setupfile一般是为了配置环境或者预置条件设置的,所以必须要最先运行,以免后续因环境问题而运行错误。
MonkeySourceRandomScript.java::MonkeySourceRandomScript(String setupFileName, ArrayList scriptFileNames…)

	//Creates a MonkeySourceRandomScript instance with an additional setup script.
    public MonkeySourceRandomScript(String setupFileName, ArrayList<String> scriptFileNames,
            long throttle, boolean randomizeThrottle, Random random, long profileWaitTime,
            long deviceSleepTime, boolean randomizeScript) {
        if (setupFileName != null) {
            mSetupSource = new MonkeySourceScript(random, setupFileName, throttle,
                    randomizeThrottle, profileWaitTime, deviceSleepTime);
            mCurrentSource = mSetupSource;
        }

        for (String fileName: scriptFileNames) {
            mScriptSources.add(new MonkeySourceScript(random, fileName, throttle,
                    randomizeThrottle, profileWaitTime, deviceSleepTime));
        }

        mRandom = random;
        mRandomizeScript = randomizeScript;
    }

2)若不包含,则随机运行所有脚本。从下面的代码可以看出不包含setup的情况下是基于包含的情况上做的处理,将setupfile视为null。
MonkeySourceRandomScript.java::MonkeySourceRandomScript(ArrayList scriptFileNames…)

	//Creates a MonkeySourceRandomScript instance without an additional setup script.
    public MonkeySourceRandomScript(ArrayList<String> scriptFileNames, long throttle,
            boolean randomizeThrottle, Random random, long profileWaitTime, long deviceSleepTime,
            boolean randomizeScript) {
        this(null, scriptFileNames, throttle, randomizeThrottle, random, profileWaitTime,
                deviceSleepTime, randomizeScript);
    }

3)MonkeySourceRandomScript本质还是脚本运行(MonkeySourceScript)
4)这里说的随机运行是通过getNextEvent()实现的,其中mCurrentSource从前面的代码可知当有setup时才被赋值

    public MonkeyEvent getNextEvent() {
    	//如果事件源为空,则从脚本源列表中随机选择新的脚本事件源,并从中选择下一个事件。
        if (mCurrentSource == null) {
            int numSources = mScriptSources.size();
            if (numSources == 1) {
                mCurrentSource = mScriptSources.get(0);
            } else if (numSources > 1 ) {
                if (mRandomizeScript) {
                    mCurrentSource = mScriptSources.get(mRandom.nextInt(numSources));
                } else {
                    mCurrentSource = mScriptSources.get(mScriptCount % numSources);
                    mScriptCount++;
                }
            }
        }
		//如果不为空时,不允许随机运行
        if (mCurrentSource != null) {
            MonkeyEvent nextEvent = mCurrentSource.getNextEvent();
            if (nextEvent == null) {
                mCurrentSource = null;
            }
            return nextEvent;
        }
        return null;
    }

3.MonkeySourceNetwork()——远程运行

 else if (mServerPort != -1) {
            try {
                mEventSource = new MonkeySourceNetwork(mServerPort);
            } catch (IOException e) {
                Logger.out.println("Error binding to network socket.");
                return -5;
            }
            mCount = Integer.MAX_VALUE;
                    } 

1)如果monkey参数包含“–port”,则通过MonkeySourceNetwork()运行远程调用
2)如何实现远程的呢?我们同样在MonkeySourceNetwork.java中的getNextEvent()中去找答案
MonkeySourceNetwork.java::getNextEvent()

    public MonkeyEvent getNextEvent() {
        if (!started) {
            try {
                startServer();   //启动,这里具体做了什么稍后详细讲解
            } catch (IOException e) {
                Log.e(TAG, "Got IOException from server", e);
                return null;
            }
            started = true;
        }
        try {
            while (true) {
                // 循环获取事件队列的下一个事件
                MonkeyEvent queuedEvent = commandQueue.getNextQueuedEvent();
                if (queuedEvent != null) {
                    // dispatch the event
                    return queuedEvent;
                }

                // Check to see if we have any returns that have been deferred. If so, now that
                // we've run the queued commands, wait for the given event to happen (or the timeout
                // to be reached), and handle the deferred MonkeyCommandReturn.
                if (deferredReturn != null) {
                    Log.d(TAG, "Waiting for event");
                    MonkeyCommandReturn ret = deferredReturn.waitForEvent();
                    deferredReturn = null;
                    handleReturn(ret);
                }

                String command = input.readLine();
                if (command == null) {
                    Log.d(TAG, "Connection dropped.");
                    // Treat this exactly the same as if the user had
                    // ended the session cleanly with a done commant.
                    command = DONE;
                }

                if (DONE.equals(command)) {
                    // stop the server so it can accept new connections
                    try {
                        stopServer();
                    } catch (IOException e) {
                        Log.e(TAG, "Got IOException shutting down!", e);
                        return null;
                    }
                    // return a noop event so we keep executing the main
                    // loop
                    return new MonkeyNoopEvent();
                }

                // Do quit checking here
                if (QUIT.equals(command)) {
                    // then we're done
                    Log.d(TAG, "Quit requested");
                    // let the host know the command ran OK
                    returnOk();
                    return null;
                }

                // Do comment checking here.  Comments aren't a
                // command, so we don't echo anything back to the
                // user.
                if (command.startsWith("#")) {
                    // keep going
                    continue;
                }

                // Translate the command line.  This will handle returning error/ok to the user
                translateCommand(command);
            }
        } catch (IOException e) {
            Log.e(TAG, "Exception: ", e);
            return null;
        }
    }

通过port实例化一个ServerSocket,通过port绑定到本地ip,
MonkeySourceNetwork.java::MonkeySourceNetwork()
MonkeySourceNetwork.java::startServer()
MonkeySourceNetwork.java::stopServer()

    public MonkeySourceNetwork(int port) throws IOException {
        // Only bind this to local host.  This means that you can only
        // talk to the monkey locally, or though adb port forwarding.
        serverSocket = new ServerSocket(port,
                                        0, // default backlog
                                        InetAddress.getLocalHost());
    }
private void startServer() throws IOException {
        clientSocket = serverSocket.accept();
        // At this point, we have a client connected.
        // Attach the accessibility listeners so that we can start receiving
        // view events. Do this before wake so we can catch the wake event
        // if possible.
        MonkeySourceNetworkViews.setup();
        // Wake the device up in preparation for doing some commands.
        wake();

        input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        // auto-flush
        output = new PrintWriter(clientSocket.getOutputStream(), true);
    }

    /**
     * Stop the server from running so it can reconnect a new client.
     */
private void stopServer() throws IOException {
        clientSocket.close();
        MonkeySourceNetworkViews.teardown();
        input.close();
        output.close();
        started = false;
    }

4.MonkeySourceRandom()——随机运行
如果既没有“-f”又没有“–setup”,则通过MonkeySourceRandom()直接随机运行。显然这是默认的方式。

else {
            // random source by default
            if (mVerbose >= 2) { // check seeding performance
                Logger.out.println("// Seeded: " + mSeed);
            }
            mEventSource = new MonkeySourceRandom(mRandom, mMainApps,
                    mThrottle, mRandomizeThrottle, mPermissionTargetSystem);
            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();
        }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值