您好,登錄后才能下訂單哦!
在《MonkeyRunner源碼分析之與Android設(shè)備通訊方式》中,我們談及到MonkeyRunner控制目標(biāo)android設(shè)備有多種方法,其中之一就是在目標(biāo)機(jī)器啟動(dòng)一個(gè)monkey服務(wù)來(lái)監(jiān)聽(tīng)指定的一個(gè)端口,然后monkeyrunner再連接上這個(gè)端口來(lái)發(fā)送命令,驅(qū)動(dòng)monkey去完成相應(yīng)的工作。
當(dāng)時(shí)我們只分析了monkeyrunner這個(gè)客戶端的代碼是怎么實(shí)現(xiàn)這一點(diǎn)的,但沒(méi)有談monkey那邊是如何接受命令,接受到命令又是如何處理的。
所以自己打開(kāi)源碼看了一個(gè)晚上,大概有了概念。但今天網(wǎng)上搜索了下,發(fā)現(xiàn)已經(jīng)有網(wǎng)友“chenjie”對(duì)monkey的源碼做過(guò)相應(yīng)的分析了,而且文章寫(xiě)得非常有概括性,應(yīng)該是高手所為,果斷花了2個(gè)積分下載下來(lái),不敢獨(dú)享,本想貼上來(lái)分享給大家,但發(fā)現(xiàn)pdf的文檔直接拷貝上來(lái)會(huì)丟失掉圖片,所以只好貼上下載地址:http://download.csdn.net/download/zqilu/6884491
但文章主要是架構(gòu)性得去描述monkey是怎么工作的,按照我自己的習(xí)慣,我還是喜歡按照自己的思維和有目的性的去了解我想要的,在這里我想要的是搞清楚monkey是如何處理monkeyrunner過(guò)來(lái)的命令的。
本文我們就先看下monkey的運(yùn)行流程。
base=/system export CLASSPATH=$base/framework/monkey.jar trap "" HUP exec app_process $base/bin com.android.commands.monkey.Monkey $*android中可以通過(guò)多種方式啟動(dòng)java應(yīng)用,通過(guò)app_process命令啟動(dòng)就是其中一種,它可以幫忙注冊(cè)android JNI,而繞過(guò)dalvik以使用Native API(如我般不清楚的請(qǐng)百度)所做的主要事情如下:
/** * Command-line entry point. * * @param args The command-line arguments */ public static void main(String[] args) { // Set the process name showing in "ps" or "top" Process.setArgV0("com.android.commands.monkey"); int resultCode = (new Monkey()).run(args); System.exit(resultCode); }
private int run(String[] args) { ... if (!processOptions()) { return -1; } ... }進(jìn)去之后就是很普通的讀取命令行的參數(shù)然后一個(gè)個(gè)進(jìn)行解析保存了,沒(méi)有太多特別的東西,這里就直接貼出monkey的參數(shù)選項(xiàng)大家看看就好了:
private int run(String[] args) { ... 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; } 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; } else if (mServerPort != -1) { try { mEventSource = new MonkeySourceNetwork(mServerPort); } catch (IOException e) { System.out.println("Error binding to network socket."); return -5; } mCount = Integer.MAX_VALUE; } else { // random source by default if (mVerbose >= 2) { // check seeding performance System.out.println("// Seeded: " + mSeed); } mEventSource = new MonkeySourceRandom(mRandom, mMainApps, mThrottle, mRandomizeThrottle); 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(); } ... mNetworkMonitor.start(); int crashedAtCycle = runMonkeyCycles(); mNetworkMonitor.stop(); ... }事件源代表測(cè)試數(shù)據(jù)的事件是從哪里過(guò)來(lái)的,不同的event source會(huì)有不同的類來(lái)做相應(yīng)的實(shí)現(xiàn):
private int run(String[] args) { ... int crashedAtCycle = runMonkeyCycles(); ... }如前所述,runMonkeyCyles方法會(huì)根據(jù)不同的數(shù)據(jù)源開(kāi)始一條條的獲取事件并進(jìn)行執(zhí)行:
/** * Run mCount cycles and see if we hit any crashers. * <p> * TODO: Meta state on keys * * @return Returns the last cycle which executed. If the value == mCount, no * errors detected. */ private int runMonkeyCycles() { int eventCounter = 0; int cycleCounter = 0; boolean shouldReportAnrTraces = false; boolean shouldReportDumpsysMemInfo = false; boolean shouldAbort = false; boolean systemCrashed = false; // TO DO : The count should apply to each of the script file. while (!systemCrashed && cycleCounter < mCount) { ... MonkeyEvent ev = mEventSource.getNextEvent(); if (ev != null) { int injectCode = ev.injectEvent(mWm, mAm, mVerbose); ... } ... } .... }注意這里的mEventSource就是我們上面提到的事件源的接口,它屏蔽了每個(gè)事件實(shí)現(xiàn)類的具體細(xì)節(jié),我們只需要告訴這個(gè)接口我們現(xiàn)在需要取一條事件然后執(zhí)行它,該結(jié)構(gòu)根據(jù)面向?qū)ο蟮亩鄳B(tài)原理,就會(huì)自動(dòng)取事件的實(shí)現(xiàn)類獲得對(duì)應(yīng)的事件進(jìn)行返回。
作者 | 自主博客 | 微信 | CSDN |
天地會(huì)珠海分舵 | http://techgogogo.com | 服務(wù)號(hào):TechGoGoGo 掃描碼:
| 向AI問(wèn)一下細(xì)節(jié) 免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。 猜你喜歡最新資訊相關(guān)推薦相關(guān)標(biāo)簽AI
助 手 |