【Android Monkey源码解析三】- 运行解析
2025-10-06 / 龙之叶   

今天,承接上文 【Android Monkey源码解析二】- 参数解析 中提到的Monkey主类进行继续解析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/**
* Run the command!
*
* @param args The command-line arguments
* @return Returns a posix-style result code. 0 for no error.
*/
private int run(String[] args) {

...

// now set up additional data in preparation for launch
// 如果在命令行参数中没有指定category(-c)的情况下,添加CATEGORY_LAUNCHER和CATEGORY_MONKEY
if (mMainCategories.size() == 0) {
mMainCategories.add(Intent.CATEGORY_LAUNCHER);
mMainCategories.add(Intent.CATEGORY_MONKEY);
}
// 如果没有设置随机种子值,则自动生成
if (mSeed == 0) {
mSeed = System.currentTimeMillis() + System.identityHashCode(this);
}
if (mVerbose > 0) {
// 打印所有的包信息和Category信息
Logger.out.println(":Monkey: seed=" + mSeed + " count=" + mCount);
MonkeyUtils.getPackageFilter().dump();
if (mMainCategories.size() != 0) {
Iterator<String> it = mMainCategories.iterator();
while (it.hasNext()) {
Logger.out.println(":IncludeCategory: " + it.next());
}
}
}
// 这个目前没有使用到,在此类中,没有任何的逻辑,都是直接返回true
if (!checkInternalConfiguration()) {
return -2;
}
// 如果获取ActivityManager,WindowManager,PackageManager系统接口对象出现异常,就直接退出
if (!getSystemInterfaces()) {
return -3;
}
// 此方法的处理,主要是通过Intent结合ACTION_MAIN和通过命令行设置的categories或默认的categories,
// 获取手机系统上所有满足条件的应用集合;然后,再跟设置的MonkeyUtils中设置的validPackages进行对比
// 过滤,若过滤后仍没有交集,则程序直接退出;若有满足的条件,则添加到mMainApps集合对象中。
if (!getMainApps()) {
return -4;
}
// 初始化Random对象,以供后续的随机事件调用
mRandom = new Random(mSeed);
// 如果命令行指令有设置Monkey的脚本参数,则进入此逻辑处理
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) {
// 如果命令行指令有设置多个Monkey的脚本参数,则进入此逻辑处理
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) {
Logger.out.println("Error binding to network socket.");
return -5;
}
mCount = Integer.MAX_VALUE;
} 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
// 首先,生成一个随机的Activity启动事件
((MonkeySourceRandom) mEventSource).generateActivity();
}
// validate source generator
if (!mEventSource.validate()) {
return -5;
}
// If we're profiling, do it immediately before/after the main monkey
// loop
if (mGenerateHprof) {
signalPersistentProcesses();
}
mNetworkMonitor.start();
int crashedAtCycle = 0;
try {
// 执行Monkey循环事件
crashedAtCycle = runMonkeyCycles();
} finally {
// Release the rotation lock if it's still held and restore the
// original orientation.
new MonkeyRotationEvent(Surface.ROTATION_0, false).injectEvent(
mWm, mAm, mVerbose);
}
mNetworkMonitor.stop();
synchronized (this) {
if (mRequestAnrTraces) {
reportAnrTraces();
mRequestAnrTraces = false;
}
if (mRequestAnrBugreport){
Logger.out.println("Print the anr report");
getBugreport("anr_" + mReportProcessName + "_");
mRequestAnrBugreport = false;
}
if (mRequestWatchdogBugreport) {
Logger.out.println("Print the watchdog report");
getBugreport("anr_watchdog_");
mRequestWatchdogBugreport = false;
}
if (mRequestAppCrashBugreport){
getBugreport("app_crash" + mReportProcessName + "_");
mRequestAppCrashBugreport = false;
}
if (mRequestDumpsysMemInfo) {
reportDumpsysMemInfo();
mRequestDumpsysMemInfo = false;
}
if (mRequestPeriodicBugreport){
getBugreport("Bugreport_");
mRequestPeriodicBugreport = false;
}
if (mWatchdogWaiting) {
mWatchdogWaiting = false;
notifyAll();
}
}
if (mGenerateHprof) {
signalPersistentProcesses();
if (mVerbose > 0) {
Logger.out.println("// Generated profiling reports in /data/misc");
}
}
// 取消ActivityController的设置
try {
mAm.setActivityController(null, true);
mNetworkMonitor.unregister(mAm);
} catch (RemoteException e) {
// just in case this was latent (after mCount cycles), make sure
// we report it
if (crashedAtCycle >= mCount) {
crashedAtCycle = mCount - 1;
}
}
// report dropped event stats
if (mVerbose > 0) {
Logger.out.println(":Dropped: keys=" + mDroppedKeyEvents
+ " pointers=" + mDroppedPointerEvents
+ " trackballs=" + mDroppedTrackballEvents
+ " flips=" + mDroppedFlipEvents
+ " rotations=" + mDroppedRotationEvents);
}
// report network stats
mNetworkMonitor.dump();
if (crashedAtCycle < mCount - 1) {
Logger.err.println("** System appears to have crashed at event " + crashedAtCycle
+ " of " + mCount + " using seed " + mSeed);
return crashedAtCycle;
} else {
if (mVerbose > 0) {
Logger.out.println("// Monkey finished");
}
return 0;
}
}

getSystemInterfaces方法通过远程调用的方式,分别获取系统的接口对象ActivityManager(mAm,后续用于判断和控制Activity的进入,主要通过设置ActivityController来实现),WindowManager(mWm ,用于处理输入等),PackageManager(mPm,获取包相关的信息 ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* Attach to the required system interfaces.
*
* @return Returns true if all system interfaces were available.
*/
private boolean getSystemInterfaces() {
mAm = ActivityManager.getService();
if (mAm == null) {
Logger.err.println("** Error: Unable to connect to activity manager; is the system "
+ "running?");
return false;
}
mWm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
if (mWm == null) {
Logger.err.println("** Error: Unable to connect to window manager; is the system "
+ "running?");
return false;
}
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
if (mPm == null) {
Logger.err.println("** Error: Unable to connect to package manager; is the system "
+ "running?");
return false;
}
try {
mAm.setActivityController(new ActivityController(), true);
mNetworkMonitor.register(mAm);
} catch (RemoteException e) {
Logger.err.println("** Failed talking with activity manager!");
return false;
}
return true;
}

后续,我们将首先分析Monkey的异常捕获和页面控制。

本文链接:
http://longzhiye.top/2025/10/06/2025-10-06/