【Android Monkey源码解析四】- 异常捕获/页面控制
2025-10-07 / 龙之叶   

承接上文,在 【Android Monkey源码解析三】- 运行解析 中,有介绍到run方法中的getSystemInterfaces方法是获取所有系统接口对象的。其中异常捕获和页面控制就是通过ActivityManager的setActivityController方法来实现的,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 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;
}
...
try {
mAm.setActivityController(new ActivityController(), true);
mNetworkMonitor.register(mAm);
} catch (RemoteException e) {
Logger.err.println("** Failed talking with activity manager!");
return false;
}
return true;
}

这里,创建了一个新的ActivityController对象,设置给了ActivityManager的setActivityController的第一个参数。下面看下ActivityController的实现,源码地址:https://android.googlesource.com/platform/development/+/refs/heads/android12-release/cmds/monkey/src/com/android/commands/monkey/Monkey.java#265

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
/**
* Monitor operations happening in the system.
* ActivityController主要实现处理了如下几个事情:
* 1. 页面控制(activityStarting)
* 2. 应用崩溃监控(appCrashed)
* 3. 应用无响应(appNotResponding)
* 4. 系统无响应(appNotResponding)
*/
private class ActivityController extends IActivityController.Stub {
public boolean activityStarting(Intent intent, String pkg) {
// 当Monkey在执行随机事件时,可能进入任何的应用。这里需要对即将进入的应用进行判断
// 如果不是目标测试应用,则不允许跳转。
final boolean allow = isActivityStartingAllowed(intent, pkg);
if (mVerbose > 0) {
// StrictMode's disk checks end up catching this on
// userdebug/eng builds due to PrintStream going to a
// FileOutputStream in the end (perhaps only when
// redirected to a file?) So we allow disk writes
// around this region for the monkey to minimize
// harmless dropbox uploads from monkeys.
StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
Logger.out.println(" // " + (allow ? "Allowing" : "Rejecting") + " start of "
+ intent + " in package " + pkg);
StrictMode.setThreadPolicy(savedPolicy);
}
currentPackage = pkg;
currentIntent = intent;
return allow;
}
// 有三种情况时允许进入目标activity,
// 1. 如果当前要进入的activity是已指定的测试应用包下的;
// 2. 如果设置了允许所有启动activity,此标志位(DEBUG_ALLOW_ANY_STARTS )无设置,条件会不满足;
// 3. 如果启动的activity是启动器的主页面;
private boolean isActivityStartingAllowed(Intent intent, String pkg) {
if (MonkeyUtils.getPackageFilter().checkEnteringPackage(pkg)) {
return true;
}
if (DEBUG_ALLOW_ANY_STARTS != 0) {
return true;
}
// In case the activity is launching home and the default launcher
// package is disabled, allow anyway to prevent ANR (see b/38121026)
final Set<String> categories = intent.getCategories();
if (intent.getAction() == Intent.ACTION_MAIN
&& categories != null
&& categories.contains(Intent.CATEGORY_HOME)) {
try {
final ResolveInfo resolveInfo =
mPm.resolveIntent(intent, intent.getType(), 0,
ActivityManager.getCurrentUser());
final String launcherPackage = resolveInfo.activityInfo.packageName;
if (pkg.equals(launcherPackage)) {
return true;
}
} catch (RemoteException e) {
Logger.err.println("** Failed talking with package manager!");
return false;
}
}
return false;
}
// 当activity进入onResume生命周期时调用
public boolean activityResuming(String pkg) {
StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
Logger.out.println(" // activityResuming(" + pkg + ")");
boolean allow = MonkeyUtils.getPackageFilter().checkEnteringPackage(pkg)
|| (DEBUG_ALLOW_ANY_RESTARTS != 0);
if (!allow) {
if (mVerbose > 0) {
Logger.out.println(" // " + (allow ? "Allowing" : "Rejecting")
+ " resume of package " + pkg);
}
}
currentPackage = pkg;
StrictMode.setThreadPolicy(savedPolicy);
return allow;
}
// 当有应用出现崩溃时调用
public boolean appCrashed(String processName, int pid,
String shortMsg, String longMsg,
long timeMillis, String stackTrace) {
StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
Logger.err.println("// CRASH: " + processName + " (pid " + pid + ")");
Logger.err.println("// Short Msg: " + shortMsg);
Logger.err.println("// Long Msg: " + longMsg);
Logger.err.println("// Build Label: " + Build.FINGERPRINT);
Logger.err.println("// Build Changelist: " + Build.VERSION.INCREMENTAL);
Logger.err.println("// Build Time: " + Build.TIME);
Logger.err.println("// " + stackTrace.replace("\n", "\n// "));
StrictMode.setThreadPolicy(savedPolicy);
// 判断是否有设置mMatchDescription,如果没设置,则直接进入第二层if处理
// 如果有设置mMatchDescription,则通过shortMsg,longMsg,stackTrace进行分别匹配,只要有满足,则进入第二层if处理
if (mMatchDescription == null
|| shortMsg.contains(mMatchDescription)
|| longMsg.contains(mMatchDescription)
|| stackTrace.contains(mMatchDescription)) {
// 如果设置mIgnoreCrashes为false或者设置了mRequestBugreport为true
if (!mIgnoreCrashes || mRequestBugreport) {
synchronized (Monkey.this) {
if (!mIgnoreCrashes) {
mAbort = true;
}
if (mRequestBugreport){
mRequestAppCrashBugreport = true;
mReportProcessName = processName;
}
}
return !mKillProcessAfterError;
}
}
return false;
}
public int appEarlyNotResponding(String processName, int pid, String annotation) {
return 0;
}
// 出现应用无响应时回调处理
public int appNotResponding(String processName, int pid, String processStats) {
StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
Logger.err.println("// NOT RESPONDING: " + processName + " (pid " + pid + ")");
Logger.err.println(processStats);
StrictMode.setThreadPolicy(savedPolicy);
// 同样地,匹配mMatchDescription设置和未设置的条件判断
if (mMatchDescription == null || processStats.contains(mMatchDescription)) {
synchronized (Monkey.this) {
mRequestAnrTraces = true;
mRequestDumpsysMemInfo = true;
mRequestProcRank = true;
if (mRequestBugreport) {
mRequestAnrBugreport = true;
mReportProcessName = processName;
}
}
if (!mIgnoreTimeouts) {
synchronized (Monkey.this) {
mAbort = true;
}
}
}
return (mKillProcessAfterError) ? -1 : 1;
}
// 出现系统无响应时回调处理
public int systemNotResponding(String message) {
StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
Logger.err.println("// WATCHDOG: " + message);
StrictMode.setThreadPolicy(savedPolicy);
synchronized (Monkey.this) {
if (mMatchDescription == null || message.contains(mMatchDescription)) {
if (!mIgnoreCrashes) {
mAbort = true;
}
if (mRequestBugreport) {
mRequestWatchdogBugreport = true;
}
}
mWatchdogWaiting = true;
}
synchronized (Monkey.this) {
while (mWatchdogWaiting) {
try {
Monkey.this.wait();
} catch (InterruptedException e) {
}
}
}
return (mKillProcessAfterError) ? -1 : 1;
}
}

本篇主要介绍了ActivityController的异常捕获/页面控制处理,下面会介绍在出现应用崩溃(appCrashed),应用无响应(appNotResponding),系统无响应时的处理分析(systemNotResponding)。

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