# 1. ActivityThread 主线程
新进程启动以后,执行的第一个 Java 程序是 ActivityThread 的 main 方法:
// frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
// Install selective syscall interception
AndroidOs.install();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
// Call per-process mainline module initialization.
initializeMainlineModules();
Process.setArgV0("<pre-initialized>");
// 关注点
Looper.prepareMainLooper();
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
// It will be in the format "seq=114"
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
// 关注点
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
// getHandler 返回的就是 mH
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// 关注点
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
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
核心的我们需要关注的,两点:
- new 了一个 ActivityThread 对象,并调用 attach,向 system_server 发起一个绑定操作,告诉 AMS,App 进程已经启动了
- 初始化应用进程的主线程的 Looper,并开启 loop 消息循环
Looper 这里在前面详细分析过了,这里就不在说了。重点放在 ActivityThread 的初始化上和 attach 方法上。
# 1.1 ActivityThread 的初始化过程
main 方法中会 new 一个 ActivityThread,先看下 ActivtiyThread 的构造方法:
public final class ActivityThread extends ClientTransactionHandler
implements ActivityThreadInternal {
// App 资源管理
private final ResourcesManager mResourcesManager;
// // App 这边的四大组件大管家
// @UnsupportedAppUsage
Instrumentation mInstrumentation;
// 主线程 Looper
@UnsupportedAppUsa ge
final Looper mLooper = Looper.myLooper();
@UnsupportedAppUsage
final H mH = new H();
// App 相关的信息
@UnsupportedAppUsage
AppBindData mBoundApplication;
// App 这边的匿名 binder 服务
@UnsupportedAppUsage
final ApplicationThread mAppThread = new ApplicationThread();
@UnsupportedAppUsage
ActivityThread() {
mResourcesManager = ResourcesManager.getInstance();
}
}
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
ActivityThread 构造方法只是初始化了 ResourcesManager,从名字就可以看出,是用于资源管理的。ActivityThread 还有几个重要成员是在声明的时候就初始化了:
final Looper mLooper
:主线程 Looperfinal H mH
:主线程绑定的 handlerfinal ApplicationThread mAppThread
:App 这边的匿名 Binder 服务,SystemServer 通过这个 Binder 服务向 App 发送 Activity 相关的状态信息
# 1.2 attach 实现分析
在接着分析 attach 方法之前,需要明白一点,AMS/ATMS/WMS 的存在,很大一部分原因是保存 App 相关的一些信息,方便统一的调度管理。比如,前面说的窗口容器树,保存的是一个页面的整个的显示结构。
这里 attach,实际就是对新进程对应的 ProcessRecord 对象内部成员赋值,我们接着看 attach 方法的具体实现:
// frameworks/base/core/java/android/app/ActivityThread.java
// 前面提到过,App 进程中初始化一个 Binder 服务端类
@UnsupportedAppUsage
final ApplicationThread mAppThread = new ApplicationThread();
@UnsupportedAppUsage
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mConfigurationController = new ConfigurationController(this);
mSystemThread = system;
mStartSeq = startSeq;
if (!system) { // App 进程走这个,系统进程走 else
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
// AMS 代理对象获取
final IActivityManager mgr = ActivityManager.getService();
try {
// //通过 Binder 远程调用 AMS 的 attachApplication 方法
mgr.attachApplication(mAppThread, startSeq); //非 oneway
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
// Watch for getting close to heap limit.
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
if (dalvikUsed > ((3*dalvikMax)/4)) {
if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
+ " total=" + (runtime.totalMemory()/1024)
+ " used=" + (dalvikUsed/1024));
mSomeActivitiesChanged = false;
try {
ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
});
} else { // 系统进程走这里
//.....
}
//为ViewRootImpl注册 Config 回调接口
ViewRootImpl.ConfigChangedCallback configChangedCallback = (Configuration globalConfig) -> {
synchronized (mResourcesManager) {
// We need to apply this change to the resources immediately, because upon returning
// the view hierarchy will be informed about it.
if (mResourcesManager.applyConfigurationToResources(globalConfig,
null /* compat */)) {
mConfigurationController.updateLocaleListFromAppContext(
mInitialApplication.getApplicationContext());
// This actually changed the resources! Tell everyone about it.
final Configuration updatedConfig =
mConfigurationController.updatePendingConfiguration(globalConfig);
if (updatedConfig != null) {
sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
mPendingConfiguration = updatedConfig;
}
}
}
};
ViewRootImpl.addConfigCallback(configChangedCallback);
}
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
App 这里通过调用 ActivityManager.getService()
获取到 AMS 的代理端对象 mgr,从而建立 App 到 AMS 的 Binder 通信通道。
接着调用 mgr.attachApplication(mAppThread, startSeq)
, mAppThread 的类型是 ApplicationThread,是一个 Binder 服务端对象,通过 mgr 的远程调用,会注册为一个匿名 Binder 服务。这样就建立了 AMS 到 App 的 Binder 通信通道
App 端的 attachApplication 会跨进程调用到 AMS 端的 attachApplication 方法,不分析代码,猜一下,进程刚创建好,跨进程和 AMS 通信,大概率是要在 AMS 中记录进程相关的信息。
具体看服务端代码:
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
// 获取一些进程相关的信息
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
// 接着调用
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
接着调用 attachApplicationLocked 方法:
方法很长,我们分段看:
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
final PidMap mPidsSelfLocked = new PidMap();
@GuardedBy("this")
private void attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
// 用于记录进程相关信息
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
long bindApplicationTimeMillis;
if (pid != MY_PID && pid >= 0) {
// 根据 PID 映射应用进程的 ProcessRecord 对象
synchronized (mPidsSelfLocked) {
// ProcessRecord 对象是在哪里创建的?
app = mPidsSelfLocked.get(pid);
}
// ......
} else {
app = null;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mPidsSelfLocked 内部有一个 SparseArray 容器,所有的 ProcessRecord 对象都保存在这里。 在启动新进程的过程中,会 new 一个 ProcessRecord 对象,并保存在 mPidsSelfLocked 中。
这里从 mPidsSelfLocked 中取出 ProcessRecord 对象。
接着往下看:
// It's possible that process called attachApplication before we got a chance to
// update the internal state.
if (app == null && startSeq > 0) { // 不进入
final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);
if (pending != null && pending.getStartUid() == callingUid
&& pending.getStartSeq() == startSeq
&& mProcessList.handleProcessStartedLocked(pending, pid,
pending.isUsingWrapper(), startSeq, true)) {
app = pending;
}
}
if (app == null) { // 不进入
Slog.w(TAG, "No pending application record for pid " + pid
+ " (IApplicationThread " + thread + "); dropping process");
EventLogTags.writeAmDropProcess(pid);
if (pid > 0 && pid != MY_PID) {
killProcessQuiet(pid);
//TODO: killProcessGroup(app.info.uid, pid);
// We can't log the app kill info for this process since we don't
// know who it is, so just skip the logging.
} else {
try {
thread.scheduleExit();
} catch (Exception e) {
// Ignore exceptions.
}
}
return;
}
// If this application record is still attached to a previous
// process, clean it up now.
if (app.getThread() != null) { // 不进入
handleAppDiedLocked(app, pid, true, true, false /* fromBinderDied */);
}
// Tell the process all about itself.
if (DEBUG_ALL) Slog.v(
TAG, "Binding process pid " + pid + " to record " + app);
final String processName = app.processName;
//给 App 端的匿名 Binder ApplicationThread 注册 Binder 死亡通知
try {
//给 App 中的 ApplicationThread 服务注册死亡通知
// App 所在进程关闭后,AMS 可以收到 Binder 驱动的通知,做一些资源包回收和数据结构的调整
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.setDeathRecipient(adr);
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
mProcessList.startProcessLocked(app,
new HostingRecord(HostingRecord.HOSTING_TYPE_LINK_FAIL, processName),
ZYGOTE_POLICY_FLAG_EMPTY);
return;
}
EventLogTags.writeAmProcBound(app.userId, pid, app.processName);
// 给 ProcessRecord 赋值
// 验证了前面的猜想
synchronized (mProcLock) {
app.mState.setCurAdj(ProcessList.INVALID_ADJ);
app.mState.setSetAdj(ProcessList.INVALID_ADJ);
app.mState.setVerifiedAdj(ProcessList.INVALID_ADJ);
mOomAdjuster.setAttachingSchedGroupLSP(app);
app.mState.setForcingToImportant(null);
clearProcessForegroundLocked(app);
app.mState.setHasShownUi(false);
app.mState.setCached(false);
app.setDebugging(false);
app.setKilledByAm(false);
app.setKilled(false);
// We carefully use the same state that PackageManager uses for
// filtering, since we use this flag to decide if we need to install
// providers when user is unlocked later
app.setUnlocked(StorageManager.isUserKeyUnlocked(app.userId));
}
// 获取应用进程的所有 Provider
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
List<ProviderInfo> providers = normalMode
? mCpHelper.generateApplicationProvidersLocked(app)
: null;
// 不进入
// 发送一个定时 Message
// 后续在 ContentProvider 发布的时候会进行解除
// 如果时间到了,ContentProvider 还没有发布,就会触发 Message 的回调方法,抛出一个 ANR
if (providers != null && mCpHelper.checkAppInLaunchingProvidersLocked(app)) {
Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg,
ContentResolver.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS);
}
checkTime(startTime, "attachApplicationLocked: before bindApplication");
if (!normalMode) {
Slog.i(TAG, "Launching preboot mode app: " + app);
}
if (DEBUG_ALL) Slog.v(
TAG, "New app record " + app
+ " thread=" + thread.asBinder() + " pid=" + pid);
final BackupRecord backupTarget = mBackupTargets.get(app.userId);
try {
int testMode = ApplicationThreadConstants.DEBUG_OFF;
if (mDebugApp != null && mDebugApp.equals(processName)) { // 不进入
if (mWaitForDebugger) {
if (mSuspendUponWait) {
testMode = ApplicationThreadConstants.DEBUG_SUSPEND;
} else {
testMode = ApplicationThreadConstants.DEBUG_WAIT;
}
} else {
testMode = ApplicationThreadConstants.DEBUG_ON;
}
app.setDebugging(true);
if (mDebugTransient) {
mDebugApp = mOrigDebugApp;
mWaitForDebugger = mOrigWaitForDebugger;
}
}
boolean enableTrackAllocation = false;
synchronized (mProcLock) {
// 不进入
if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
enableTrackAllocation = true;
mTrackAllocationApp = null;
}
}
// If the app is being launched for restore or full backup, set it up specially
boolean isRestrictedBackupMode = false;
// 不进入
if (backupTarget != null && backupTarget.appInfo.packageName.equals(processName)) {
isRestrictedBackupMode = backupTarget.appInfo.uid >= FIRST_APPLICATION_UID
&& ((backupTarget.backupMode == BackupRecord.RESTORE_FULL)
|| (backupTarget.backupMode == BackupRecord.BACKUP_FULL));
}
final ActiveInstrumentation instr = app.getActiveInstrumentation();
if (instr != null) {
notifyPackageUse(instr.mClass.getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_INSTRUMENTATION);
}
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Binding proc %s with config %s",
processName, app.getWindowProcessController().getConfiguration());
//
ApplicationInfo appInfo = instr != null ? instr.mTargetInfo : app.info;
app.setCompat(compatibilityInfoForPackage(appInfo));
//
ProfilerInfo profilerInfo = mAppProfiler.setupProfilerInfoLocked(thread, app, instr);
// We deprecated Build.SERIAL and it is not accessible to
// Instant Apps and target APIs higher than O MR1. Since access to the serial
// is now behind a permission we push down the value.
final String buildSerial = (!appInfo.isInstantApp()
&& appInfo.targetSdkVersion < Build.VERSION_CODES.P)
? sTheRealBuildSerial : Build.UNKNOWN;
// Figure out whether the app needs to run in autofill compat mode.
AutofillOptions autofillOptions = null;
// 不进入
if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) {
final AutofillManagerInternal afm = LocalServices.getService(
AutofillManagerInternal.class);
if (afm != null) {
autofillOptions = afm.getAutofillOptions(
app.info.packageName, app.info.longVersionCode, app.userId);
}
}
//不进入
ContentCaptureOptions contentCaptureOptions = null;
if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) {
final ContentCaptureManagerInternal ccm =
LocalServices.getService(ContentCaptureManagerInternal.class);
if (ccm != null) {
contentCaptureOptions = ccm.getOptionsForPackage(app.userId,
app.info.packageName);
}
}
SharedMemory serializedSystemFontMap = null;
final FontManagerInternal fm = LocalServices.getService(FontManagerInternal.class);
if (fm != null) { //进入
serializedSystemFontMap = fm.getSerializedSystemFontMap();
}
checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
bindApplicationTimeMillis = SystemClock.uptimeMillis();
mAtmInternal.preBindApplication(app.getWindowProcessController());
final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
if (mPlatformCompat != null) { // 进入
mPlatformCompat.resetReporting(app.info);
}
final ProviderInfoList providerList = ProviderInfoList.fromList(providers);
if (app.getIsolatedEntryPoint() != null) { // 不进入
// This is an isolated process which should just call an entry point instead of
// being bound to an application.
thread.runIsolatedEntryPoint(
app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
} else if (instr2 != null) { // 不进入
thread.bindApplication(processName, appInfo,
app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
providerList,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.getDisabledCompatChanges(), serializedSystemFontMap,
app.getStartElapsedTime(), app.getStartUptime());
} else { // 走这个分支
// 前面一大堆的代码,实际都在准备 bindApplication 的参数
// 远程调用到 App 端
thread.bindApplication(processName, appInfo,
app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
providerList, null, profilerInfo, null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.getDisabledCompatChanges(), serializedSystemFontMap,
app.getStartElapsedTime(), app.getStartUptime());
}
if (profilerInfo != null) {
profilerInfo.closeFd();
profilerInfo = null;
}
app.setBindApplicationTime(bindApplicationTimeMillis);
// Make app active after binding application or client may be running requests (e.g
// starting activities) before it is ready.
synchronized (mProcLock) {
//
app.makeActive(thread, mProcessStats);
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
}
updateLruProcessLocked(app, false, null);
checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
final long now = SystemClock.uptimeMillis();
synchronized (mAppProfiler.mProfilerLock) {
app.mProfile.setLastRequestedGc(now);
app.mProfile.setLastLowMemory(now);
}
// Remove this record from the list of starting applications.
mPersistentStartingProcesses.remove(app);
if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) {
Slog.v(TAG_PROCESSES, "Attach application locked removing on hold: " + app);
}
mProcessesOnHold.remove(app);
if (!mConstants.mEnableWaitForFinishAttachApplication) {
// 关注点
finishAttachApplicationInner(startSeq, callingUid, pid);
} else {
app.setPendingFinishAttach(true);
}
} catch (Exception e) {
// We need kill the process group here. (b/148588589)
Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
app.killLocked("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
true);
handleAppDiedLocked(app, pid, false, true, false /* fromBinderDied */);
return;
}
}
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
在给 ProcessRecord 赋值后,接着会调用 bindApplication 和 finishAttachApplicationInner 方法。
# 2. bindApplication 远程调用到 App 端
bindApplication 是 oneway 方法,异步的,立即返回,接着执行后续的代码。
bindApplication 会远程调用到 App 端, App 端的实现如下:
// frameworks/base/core/java/android/app/ActivityThread.java
// # bindApplication
public final void bindApplication(String processName, ApplicationInfo appInfo,
String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
ProviderInfoList providerList, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges,
SharedMemory serializedSystemFontMap,
long startRequestedElapsedTime, long startRequestedUptime) {
if (services != null) {
if (false) {
// Test code to make sure the app could see the passed-in services.
for (Object oname : services.keySet()) {
if (services.get(oname) == null) {
continue; // AM just passed in a null service.
}
String name = (String) oname;
// See b/79378449 about the following exemption.
switch (name) {
case "package":
case Context.WINDOW_SERVICE:
continue;
}
if (ServiceManager.getService(name) == null) {
Log.wtf(TAG, "Service " + name + " should be accessible by this app");
}
}
}
// 此处缓存的是通过 bindApplication 传递过来的 PKMS,WMS,ALARM_SERVICE 代理端
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
// 构造一个 AppBindData 对象,其中保存了 App 相关的信息,这些信息主要来自方法参数,这些参数来自 AMS
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.sdkSandboxClientAppVolumeUuid = sdkSandboxClientAppVolumeUuid;
data.sdkSandboxClientAppPackage = sdkSandboxClientAppPackage;
data.providers = providerList.getList();
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
data.autofillOptions = autofillOptions;
data.contentCaptureOptions = contentCaptureOptions;
data.disabledCompatChanges = disabledCompatChanges;
data.mSerializedSystemFontMap = serializedSystemFontMap;
data.startRequestedElapsedTime = startRequestedElapsedTime;
data.startRequestedUptime = startRequestedUptime;
updateCompatOverrideScale(compatInfo);
CompatibilityInfo.applyOverrideScaleIfNeeded(config);
// 发一个 Message
sendMessage(H.BIND_APPLICATION, data);
}
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
这里会发送一个 Message,Message 的 what 是 BIND_APPLICATION
// #H
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
// ......
}
2
3
4
5
6
7
8
9
10
11
12
接着就会调用到 Message 的处理方法 handleBindApplication:
// ActivityThread.java
@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
// Register the UI Thread as a sensitive thread to the runtime.
VMRuntime.registerSensitiveThread();
// In the case the stack depth property exists, pass it down to the runtime.
String property = SystemProperties.get("debug.allocTracker.stackDepth");
if (property.length() != 0) {
VMDebug.setAllocTrackerStackDepth(Integer.parseInt(property));
}
if (data.trackAllocation) {
DdmVmInternal.setRecentAllocationsTrackingEnabled(true);
}
// Note when this process has started.
// 虽然说目标 Actiivity 进程在之前已经 fork 出来了,但是系统直到此时才是它的开端
Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis(),
data.startRequestedElapsedTime, data.startRequestedUptime);
AppCompatCallbacks.install(data.disabledCompatChanges);
// Let libcore handle any compat changes after installing the list of compat changes.
AppSpecializationHooks.handleCompatChangesBeforeBindingApplication();
// Initialize the zip path validator callback depending on the targetSdk.
// This has to be after AppCompatCallbacks#install() so that the Compat
// checks work accordingly.
initZipPathValidatorCallback();
mBoundApplication = data;
mConfigurationController.setConfiguration(data.config);
mConfigurationController.setCompatConfiguration(data.config);
mConfiguration = mConfigurationController.getConfiguration();
mCompatibilityInfo = data.compatInfo;
// Profiler 是什么?
// 好像是 Android Studio 中的性能分析工具
mProfiler = new Profiler();·
String agent = null;
if (data.initProfilerInfo != null) {
mProfiler.profileFile = data.initProfilerInfo.profileFile;
mProfiler.profileFd = data.initProfilerInfo.profileFd;
mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
mProfiler.mClockType = data.initProfilerInfo.clockType;
if (data.initProfilerInfo.attachAgentDuringBind) {
agent = data.initProfilerInfo.agent;
}
}
// 设置进程名
// send up app name; do this *before* waiting for debugger
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName,
data.appInfo.packageName,
UserHandle.myUserId());
VMRuntime.setProcessPackageName(data.appInfo.packageName);
// Pass data directory path to ART. This is used for caching information and
// should be set before any application code is loaded.
VMRuntime.setProcessDataDirectory(data.appInfo.dataDir);
if (mProfiler.profileFd != null) {
mProfiler.startProfiling();
}
// If the app is Honeycomb MR1 or earlier, switch its AsyncTask
// implementation to use the pool executor. Normally, we use the
// serialized executor as the default. This has to happen in the
// main thread so the main looper is set right.
if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
// Let the util.*Array classes maintain "undefined" for apps targeting Pie or earlier.
UtilConfig.setThrowExceptionForUpperArrayOutOfBounds(
data.appInfo.targetSdkVersion >= Build.VERSION_CODES.Q);
Message.updateCheckRecycle(data.appInfo.targetSdkVersion);
// Supply the targetSdkVersion to the UI rendering module, which may
// need it in cases where it does not have access to the appInfo.
android.graphics.Compatibility.setTargetSdkVersion(data.appInfo.targetSdkVersion);
/*
* Before spawning a new process, reset the time zone to be the system time zone.
* This needs to be done because the system time zone could have changed after the
* the spawning of this process. Without doing this this process would have the incorrect
* system time zone.
*/
TimeZone.setDefault(null);
/*
* Set the LocaleList. This may change once we create the App Context.
*/
LocaleList.setDefault(data.config.getLocales());
if (Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) {
try {
Typeface.setSystemFontMap(data.mSerializedSystemFontMap);
} catch (IOException | ErrnoException e) {
Slog.e(TAG, "Failed to parse serialized system font map");
Typeface.loadPreinstalledSystemFontMap();
}
}
synchronized (mResourcesManager) {
/*
* Update the system configuration since its preloaded and might not
* reflect configuration changes. The configuration object passed
* in AppBindData can be safely assumed to be up to date
*/
mResourcesManager.applyConfigurationToResources(data.config, data.compatInfo);
mCurDefaultDisplayDpi = data.config.densityDpi;
// This calls mResourcesManager so keep it within the synchronized block.
mConfigurationController.applyCompatConfiguration();
}
final boolean isSdkSandbox = data.sdkSandboxClientAppPackage != null;
data.info = getPackageInfo(data.appInfo, mCompatibilityInfo, null /* baseLoader */,
false /* securityViolation */, true /* includeCode */,
false /* registerPackage */, isSdkSandbox);
if (isSdkSandbox) {
data.info.setSdkSandboxStorage(data.sdkSandboxClientAppVolumeUuid,
data.sdkSandboxClientAppPackage);
}
if (agent != null) {
handleAttachAgent(agent, data.info);
}
/**
* Switch this process to density compatibility mode if needed.
*/
if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
== 0) {
mDensityCompatMode = true;
Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
}
mConfigurationController.updateDefaultDensity(data.config.densityDpi);
// mCoreSettings is only updated from the main thread, while this function is only called
// from main thread as well, so no need to lock here.
final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24);
Boolean is24Hr = null;
if (use24HourSetting != null) {
is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE;
}
// null : use locale default for 12/24 hour formatting,
// false : use 12 hour format,
// true : use 24 hour format.
DateFormat.set24HourTimePref(is24Hr);
updateDebugViewAttributeState();
StrictMode.initThreadDefaults(data.appInfo);
StrictMode.initVmDefaults(data.appInfo);
// Allow binder tracing, and application-generated systrace messages if we're profileable.
boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
boolean isAppProfileable = isAppDebuggable || data.appInfo.isProfileable();
Trace.setAppTracingAllowed(isAppProfileable);
if ((isAppProfileable || Build.IS_DEBUGGABLE) && data.enableBinderTracking) {
Binder.enableStackTracking();
}
// Initialize heap profiling.
if (isAppProfileable || Build.IS_DEBUGGABLE) {
nInitZygoteChildHeapProfiling();
}
// Allow renderer debugging features if we're debuggable.
HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
HardwareRenderer.setPackageName(data.appInfo.packageName);
// Pass the current context to HardwareRenderer
HardwareRenderer.setContextForInit(getSystemContext());
if (data.persistent) {
HardwareRenderer.setIsSystemOrPersistent();
}
// Instrumentation info affects the class loader, so load it before
// setting up the app context.
final InstrumentationInfo ii;
if (data.instrumentationName != null) {
ii = prepareInstrumentation(data);
} else {
ii = null;
}
// 获取 AMS 服务代理端
final IActivityManager mgr = ActivityManager.getService();
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
mConfigurationController.updateLocaleListFromAppContext(appContext);
// Initialize the default http proxy in this process.
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies");
try {
// In pre-boot mode (doing initial launch to collect password), not all system is up.
// This includes the connectivity service, so trying to obtain ConnectivityManager at
// that point would return null. Check whether the ConnectivityService is available, and
// avoid crashing with a NullPointerException if it is not.
final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
final ConnectivityManager cm =
appContext.getSystemService(ConnectivityManager.class);
Proxy.setHttpProxyConfiguration(cm.getDefaultProxy());
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
if (!Process.isIsolated()) {
final int oldMask = StrictMode.allowThreadDiskWritesMask();
try {
setupGraphicsSupport(appContext);
} finally {
StrictMode.setThreadPolicyMask(oldMask);
}
} else {
HardwareRenderer.setIsolatedProcess(true);
}
// Install the Network Security Config Provider. This must happen before the application
// code is loaded to prevent issues with instances of TLS objects being created before
// the provider is installed.
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "NetworkSecurityConfigProvider.install");
NetworkSecurityConfigProvider.install(appContext);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// For backward compatibility, TrafficStats needs static access to the application context.
// But for isolated apps which cannot access network related services, service discovery
// is restricted. Hence, calling this would result in NPE.
if (!Process.isIsolated()) {
TrafficStats.init(appContext);
}
// 初始化 Instrumentation,四大组件 App 端的管家
// Continue loading instrumentation.
if (ii != null) {
initInstrumentation(ii, data, appContext);
} else {
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
}
if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
} else {
// Small heap, clamp to the current growth limit and let the heap release
// pages after the growth limit to the non growth limit capacity. b/18387825
dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
}
// Allow disk access during application and provider setup. This could
// block processing ordered broadcasts, but later processing would
// probably end up doing the same disk access.
Application app;
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
waitForDebugger(data);
} else if (data.debugMode == ApplicationThreadConstants.DEBUG_SUSPEND) {
suspendAllAndSendVmStart(data);
}
// Nothing special to do in case of DEBUG_ON.
}
try {
// 初始化 Application
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
app = data.info.makeApplicationInner(data.restrictedBackupMode, null);
// Propagate autofill compat state
app.setAutofillOptions(data.autofillOptions);
// Propagate Content Capture options
app.setContentCaptureOptions(data.contentCaptureOptions);
sendMessage(H.SET_CONTENT_CAPTURE_OPTIONS_CALLBACK, data.appInfo.packageName);
mInitialApplication = app;
final boolean updateHttpProxy;
synchronized (this) {
updateHttpProxy = mUpdateHttpProxyOnBind;
// This synchronized block ensures that any subsequent call to updateHttpProxy()
// will see a non-null mInitialApplication.
}
if (updateHttpProxy) {
ActivityThread.updateHttpProxy(app);
}
// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
}
}
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
// Instrumentation onCreate
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
// Application OnCreate
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
// If the app targets < O-MR1, or doesn't change the thread policy
// during startup, clobber the policy to maintain behavior of b/36951662
if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
|| StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
StrictMode.setThreadPolicy(savedPolicy);
}
}
// 加载字体资源
// Preload fonts resources
FontsContract.setApplicationContextForResources(appContext);
if (!Process.isIsolated()) {
try {
final ApplicationInfo info =
getPackageManager().getApplicationInfo(
data.appInfo.packageName,
PackageManager.GET_META_DATA /*flags*/,
UserHandle.myUserId());
if (info.metaData != null) {
final int preloadedFontsResource = info.metaData.getInt(
ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
if (preloadedFontsResource != 0) {
data.info.getResources().preloadFonts(preloadedFontsResource);
}
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
try {
mgr.finishAttachApplication(mStartSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
- 初始化四大组件管家 Instrumentation
- 初始化 Application,执行 onCreate 生命周期回调
- 加载字体资源
# 3. finishAttachApplicationInner
回到 AMS 这边,接着执行 finishAttachApplicationInner
:
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
final long startTime = SystemClock.uptimeMillis();
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
final ProcessRecord app;
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
if (app != null && app.getStartUid() == uid && app.getStartSeq() == startSeq) {
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
} else {
Slog.wtf(TAG, "Mismatched or missing ProcessRecord: " + app + ". Pid: " + pid
+ ". Uid: " + uid);
killProcess(pid);
killProcessGroup(uid, pid);
mProcessList.noteAppKill(pid, uid,
ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
ApplicationExitInfo.SUBREASON_UNKNOWN,
"wrong startSeq");
synchronized (this) {
app.killLocked("unexpected process record",
ApplicationExitInfo.REASON_OTHER, true);
}
return;
}
synchronized (this) {
// Mark the finish attach application phase as completed
app.setPendingFinishAttach(false);
final boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
final String processName = app.processName;
boolean badApp = false;
boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
// 关注点
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
// Find any services that should be running in this process...
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
checkTime(startTime, "finishAttachApplicationInner: "
+ "after mServices.attachApplicationLocked");
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
// Check if a next-broadcast receiver is in this process...
if (!badApp) {
try {
for (BroadcastQueue queue : mBroadcastQueues) {
didSomething |= queue.onApplicationAttachedLocked(app);
}
checkTime(startTime, "finishAttachApplicationInner: "
+ "after dispatching broadcasts");
} catch (BroadcastDeliveryFailedException e) {
// If the app died trying to launch the receiver we declare it 'bad'
Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
badApp = true;
}
}
// Check whether the next backup agent is in this process...
final BackupRecord backupTarget = mBackupTargets.get(app.userId);
if (!badApp && backupTarget != null && backupTarget.app == app) {
if (DEBUG_BACKUP) {
Slog.v(TAG_BACKUP,
"New app is backup target, launching agent for " + app);
}
notifyPackageUse(backupTarget.appInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
try {
app.getThread().scheduleCreateBackupAgent(backupTarget.appInfo,
backupTarget.backupMode, backupTarget.userId,
backupTarget.backupDestination);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
badApp = true;
}
}
if (badApp) {
app.killLocked("error during init",
ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
handleAppDiedLocked(app, pid, false, true, false /* fromBinderDied */);
return;
}
if (!didSomething) {
updateOomAdjLocked(app, OOM_ADJ_REASON_PROCESS_BEGIN);
checkTime(startTime, "finishAttachApplicationInner: after updateOomAdjLocked");
}
final HostingRecord hostingRecord = app.getHostingRecord();
final String shortAction = getShortAction(hostingRecord.getAction());
FrameworkStatsLog.write(
FrameworkStatsLog.PROCESS_START_TIME,
app.info.uid,
pid,
app.info.packageName,
FrameworkStatsLog.PROCESS_START_TIME__TYPE__COLD,
app.getStartElapsedTime(),
(int) (app.getBindApplicationTime() - app.getStartUptime()),
(int) (SystemClock.uptimeMillis() - app.getStartUptime()),
hostingRecord.getType(),
hostingRecord.getName(),
shortAction,
HostingRecord.getHostingTypeIdStatsd(hostingRecord.getType()),
HostingRecord.getTriggerTypeForStatsd(hostingRecord.getTriggerType()));
}
}
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
finishAttachApplicationInner
中会接着调用
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
进入到 ATMS 这边
// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
synchronized (mGlobalLockWithoutBoost) {
if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
}
try {
return mRootWindowContainer.attachApplication(wpc);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
接着调用 attachApplication:
// /frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean attachApplication(WindowProcessController app) throws RemoteException {
try {
return mAttachApplicationHelper.process(app);
} finally {
mAttachApplicationHelper.reset();
}
}
2
3
4
5
6
7
8
mAttachApplicationHelper.process :
// /frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
// AttachApplicationHelper 是 RootWindowContainer 的内部类
private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {
// ......
boolean process(WindowProcessController app) throws RemoteException {
mApp = app;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
getChildAt(displayNdx).forAllRootTasks(this); // 子节点是 DisplayContent
if (mRemoteException != null) {
throw mRemoteException;
}
}
if (!mHasActivityStarted) {
ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
false /* preserveWindows */);
}
return mHasActivityStarted;
}
// .....
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
forAllRootTasks 遍历所有子节点:
void forAllRootTasks(Consumer<Task> callback) {
forAllRootTasks(callback, true /* traverseTopToBottom */);
}
void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
int count = mChildren.size();
if (traverseTopToBottom) { // true
for (int i = count - 1; i >= 0; --i) {
mChildren.get(i).forAllRootTasks(callback, traverseTopToBottom);
}
} else {
// ......
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
会一直递归下去,直到遍历到 Task 节点:
@Override
void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
if (isRootTask()) {
callback.accept(this);
}
}
2
3
4
5
6
执行回调方法 accept:
private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {
// ......
@Override
public void accept(Task rootTask) {
if (mRemoteException != null) {
return;
}
if (rootTask.getVisibility(null /* starting */)
== TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
return;
}
mTop = rootTask.topRunningActivity();
rootTask.forAllActivities(this);
}
// ......
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
forAllActivities 遍历 Task 的所有 ActivityRecord 子节点:
boolean forAllActivities(Predicate<ActivityRecord> callback) {
return forAllActivities(callback, true /*traverseTopToBottom*/);
}
boolean forAllActivities(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
if (traverseTopToBottom) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
}
} else {
final int count = mChildren.size();
for (int i = 0; i < count; i++) {
if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
}
}
return false;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
一样的递归,直到 ActivityRecord 节点:
@Override
boolean forAllActivities(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
return callback.test(this);
}
2
3
4
调用到回调方法 test:
// # AttachApplicationHelper
@Override
public boolean test(ActivityRecord r) {
// 找到目标 ActivityRecord
if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard
|| r.app != null || mApp.mUid != r.info.applicationInfo.uid
|| !mApp.mName.equals(r.processName)) {
return false;
}
try {
if (mTaskSupervisor.realStartActivityLocked(r, mApp,
mTop == r && r.getTask().canBeResumed(r) /* andResume */,
true /* checkConfig */)) {
mHasActivityStarted = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity " + mTop, e);
mRemoteException = e;
return true;
}
return false;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
这里会执行 mTaskSupervisor.realStartActivityLocked
:
// frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
// 检查 pause 完成没有
if (!mRootWindowContainer.allPausedActivitiesComplete()) {
// While there are activities pausing we skipping starting any new activities until
// pauses are complete. NOTE: that we also do this for activities that are starting in
// the paused state because they will first be resumed then paused on the client side.
ProtoLog.v(WM_DEBUG_STATES,
"realStartActivityLocked: Skipping start of r=%s some activities pausing...",
r);
return false;
}
final Task task = r.getTask();
final Task rootTask = task.getRootTask();
beginDeferResume();
// The LaunchActivityItem also contains process configuration, so the configuration change
// from WindowProcessController#setProcess can be deferred. The major reason is that if
// the activity has FixedRotationAdjustments, it needs to be applied with configuration.
// In general, this reduces a binder transaction if process configuration is changed.
proc.pauseConfigurationDispatch();
try {
r.startFreezingScreenLocked(proc, 0);
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();
r.lastLaunchTime = SystemClock.uptimeMillis();
r.setProcess(proc);
// Ensure activity is allowed to be resumed after process has set.
if (andResume && !r.canResumeByCompat()) {
andResume = false;
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
// Have the window manager re-evaluate the orientation of the screen based on the new
// activity order. Note that as a result of this, it can call back into the activity
// manager with a new orientation. We don't care about that, because the activity is
// not currently running so we are just restarting it anyway.
if (checkConfig) {
// Deferring resume here because we're going to launch new activity shortly.
// We don't want to perform a redundant launch of the same record while ensuring
// configurations and trying to resume top activity of focused root task.
mRootWindowContainer.ensureVisibilityAndConfig(r, r.getDisplayId(),
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
if (mKeyguardController.checkKeyguardVisibility(r) && r.allowMoveToFront()) {
// We only set the visibility to true if the activity is not being launched in
// background, and is allowed to be visible based on keyguard state. This avoids
// setting this into motion in window manager that is later cancelled due to later
// calls to ensure visible activities that set visibility back to false.
r.setVisibility(true);
}
final int applicationInfoUid =
(r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
if ((r.mUserId != proc.mUserId) || (r.info.applicationInfo.uid != applicationInfoUid)) {
Slog.wtf(TAG,
"User ID for activity changing for " + r
+ " appInfo.uid=" + r.info.applicationInfo.uid
+ " info.ai.uid=" + applicationInfoUid
+ " old=" + r.app + " new=" + proc);
}
// Send the controller to client if the process is the first time to launch activity.
// So the client can save binder transactions of getting the controller from activity
// task manager service.
final IActivityClientController activityClientController =
proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController;
r.launchCount++;
if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);
final LockTaskController lockTaskController = mService.getLockTaskController();
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
|| task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV
|| (task.mLockTaskAuth == LOCK_TASK_AUTH_ALLOWLISTED
&& lockTaskController.getLockTaskModeState()
== LOCK_TASK_MODE_LOCKED)) {
lockTaskController.startLockTaskMode(task, false, 0 /* blank UID */);
}
try {
if (!proc.hasThread()) {
throw new RemoteException();
}
List<ResultInfo> results = null;
List<ReferrerIntent> newIntents = null;
if (andResume) {
// We don't need to deliver new intents and/or set results if activity is going
// to pause immediately after launch.
results = r.results;
newIntents = r.newIntents;
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Launching: " + r + " savedState=" + r.getSavedState()
+ " with results=" + results + " newIntents=" + newIntents
+ " andResume=" + andResume);
EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
task.mTaskId, r.shortComponentName);
if (r.isActivityTypeHome()) {
// Home process is the root process of the task.
updateHomeProcess(task.getBottomMostActivity().app);
}
mService.getPackageManagerInternalLocked().notifyPackageUse(
r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);
r.forceNewConfig = false;
mService.getAppWarningsLocked().onStartActivity(r);
// Because we could be starting an Activity in the system process this may not go
// across a Binder interface which would create a new Configuration. Consequently
// we have to always create a new Configuration here.
final Configuration procConfig = proc.prepareConfigurationForLaunchingActivity();
final MergedConfiguration mergedConfiguration = new MergedConfiguration(
procConfig, r.getMergedOverrideConfiguration());
r.setLastReportedConfiguration(mergedConfiguration);
logIfTransactionTooLarge(r.intent, r.getSavedState());
final TaskFragment organizedTaskFragment = r.getOrganizedTaskFragment();
if (organizedTaskFragment != null) {
// Sending TaskFragmentInfo to client to ensure the info is updated before
// the activity creation.
mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent(
organizedTaskFragment);
}
// 创建 Activity 启动事务
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.token);
final boolean isTransitionForward = r.isTransitionForward();
final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
final int deviceId = getDeviceIdForDisplayId(r.getDisplayId());
// callback 是 LaunchActivityItem
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), deviceId,
r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
results, newIntents, r.takeOptions(), isTransitionForward,
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) { //走这个分支
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward,
r.shouldSendCompatFakeFocus());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
// Request 是 ResumeActivityItem
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// 关注点
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
if (procConfig.seq > mRootWindowContainer.getConfiguration().seq) {
// If the seq is increased, there should be something changed (e.g. registered
// activity configuration).
proc.setLastReportedConfiguration(procConfig);
}
if ((proc.mInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0
&& mService.mHasHeavyWeightFeature) {
// This may be a heavy-weight process! Note that the package manager will ensure
// that only activity can run in the main process of the .apk, which is the only
// thing that will be considered heavy-weight.
if (proc.mName.equals(proc.mInfo.packageName)) {
if (mService.mHeavyWeightProcess != null
&& mService.mHeavyWeightProcess != proc) {
Slog.w(TAG, "Starting new heavy weight process " + proc
+ " when already running "
+ mService.mHeavyWeightProcess);
}
mService.setHeavyWeightProcess(r);
}
}
} catch (RemoteException e) {
if (r.launchFailed) {
// This is the second time we failed -- finish activity and give up.
Slog.e(TAG, "Second failure launching "
+ r.intent.getComponent().flattenToShortString() + ", giving up", e);
proc.appDied("2nd-crash");
r.finishIfPossible("2nd-crash", false /* oomAdj */);
return false;
}
// This is the first time we failed -- restart process and
// retry.
r.launchFailed = true;
r.detachFromProcess();
throw e;
}
} finally {
endDeferResume();
proc.resumeConfigurationDispatch();
}
r.launchFailed = false;
// TODO(lifecycler): Resume or pause requests are done as part of launch transaction,
// so updating the state should be done accordingly.
if (andResume && readyToResume()) {
// As part of the process of launching, ActivityThread also performs
// a resume.
rootTask.minimalResumeActivityLocked(r);
} else {
// This activity is not starting in the resumed state... which should look like we asked
// it to pause+stop (but remain visible), and it has done so and reported back the
// current icicle and other state.
ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s "
+ "(starting in paused state)", r);
r.setState(PAUSED, "realStartActivityLocked");
mRootWindowContainer.executeAppTransitionForAllDisplay();
}
// Perform OOM scoring after the activity state is set, so the process can be updated with
// the latest state.
proc.onStartActivity(mService.mTopProcessState, r.info);
// Launch the new version setup screen if needed. We do this -after-
// launching the initial activity (that is, home), so that it can have
// a chance to initialize itself while in the background, making the
// switch back to it faster and look better.
if (mRootWindowContainer.isTopDisplayFocusedRootTask(rootTask)) {
mService.getActivityStartController().startSetupActivity();
}
// Update any services we are bound to that might care about whether
// their client may have activities.
if (r.app != null) {
r.app.updateServiceConnectionActivities();
}
return true;
}
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
接着调用 mService.getLifecycleManager().scheduleTransaction
向 App 端发起 Binder RPC 调用:
// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
private final ClientLifecycleManager mLifecycleManager;
ClientLifecycleManager getLifecycleManager() {
return mLifecycleManager;
}
// /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
/**
* Schedule a single lifecycle request or callback to client activity.
* @param client Target client.
* @param activityToken Target activity token.
* @param stateRequest A request to move target activity to a desired lifecycle state.
* @throws RemoteException
*
* @see ClientTransactionItem
*/
void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
@NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
stateRequest);
scheduleTransaction(clientTransaction);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
接着调用重载 scheduleTransaction:
// /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
// 关注点
transaction.schedule();
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
接着调用 schedule:
// /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
/** Target client. */
private IApplicationThread mClient;
/**
* Schedule the transaction after it was initialized. It will be send to client and all its
* individual parts will be applied in the following sequence:
* 1. The client calls {@link #preExecute(ClientTransactionHandler)}, which triggers all work
* that needs to be done before actually scheduling the transaction for callbacks and
* lifecycle state request.
* 2. The transaction message is scheduled.
* 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
* all callbacks and necessary lifecycle transitions.
*/
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
层层调用到 IApplicationThread 的 scheduleTransaction 方法,这是一个 Binder RPC 调用:
远程调用 App 端的 scheduleTransaction 方法。
远程调用到 App 端:
// /frameworks/base/core/java/android/app/ActivityThread.java
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
2
3
4
5
6
7
8
9
10
11
这里会发送一个 Message,ActivityThread 中的 Handler 中会处理到这个 Message:
// /frameworks/base/core/java/android/app/ActivityThread.java
public void handleMessage(Message msg) {
case EXECUTE_TRANSACTION:
// 从 Message 中取出消息
final ClientTransaction transaction = (ClientTransaction) msg.obj;
// 执行消息
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 从 Message 中取出消息
- 执行消息
接着我们来看执行消息的过程:
// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
// ......
// 执行回调
// LaunchActivityItem
executeCallbacks(transaction);
// 执行生命周期
// ResumeActivityItem
executeLifecycleState(transaction);
mPendingActions.clear();
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
先看 executeCallbacks
执行回调:
// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void executeCallbacks(ClientTransaction transaction) {
// 拿到 callback
// 返回的就是 ATMS 中设置的 LaunchActivityItem
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
if (callbacks == null || callbacks.isEmpty()) {
// No callbacks to execute, return early.
return;
}
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callbacks in transaction");
final IBinder token = transaction.getActivityToken();
ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
// In case when post-execution state of the last callback matches the final state requested
// for the activity in this transaction, we won't do the last transition here and do it when
// moving to final state instead (because it may contain additional parameters from server).
final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
: UNDEFINED;
// Index of the last callback that requests some post-execution state.
final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);
final int size = callbacks.size();
for (int i = 0; i < size; ++i) { // 遍历 callbacks
final ClientTransactionItem item = callbacks.get(i);
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
final int postExecutionState = item.getPostExecutionState();
final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
item.getPostExecutionState());
if (closestPreExecutionState != UNDEFINED) {
cycleToPath(r, closestPreExecutionState, transaction);
}
// 依次执行 LaunchActivityItem 的 execute 和 postExecute 方法
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
if (r == null) {
// Launch activity request will create an activity record.
r = mTransactionHandler.getActivityClient(token);
}
if (postExecutionState != UNDEFINED && r != null) {
// Skip the very last transition and perform it by explicit state request instead.
final boolean shouldExcludeLastTransition =
i == lastCallbackRequestingState && finalState == postExecutionState;
cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction);
}
}
}
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
接着看 LaunchActivityItem
的 execute 和 postExecute 方法:
//
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
// 构建好 ActivityClientRecord 对象,客户端这边描述 Activity 的对象
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client, mAssistToken);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@Override
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
client.countLaunchingActivities(-1);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
接着执行 ActivityThread 的 handleLaunchActivity 和 countLaunchingActivities 方法:
// frameworks/base/core/java/android/app/ActivityThread.java
/**
* Extended implementation of activity launch. Used when server requests a launch or relaunch.
*/
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
if (!ThreadedRenderer.sRendererDisabled
&& (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
HardwareRenderer.preload();
}
WindowManagerGlobal.initialize();
// Hint the GraphicsEnvironment that an activity is launching on the process.
GraphicsEnvironment.hintActivityLaunch();
// 接着调用 performLaunchActivity
final Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
if (!r.activity.mFinished && pendingActions != null) {
pendingActions.setOldState(r.state);
pendingActions.setRestoreInstanceState(true);
pendingActions.setCallOnPostCreate(true);
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityTaskManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
return a;
}
// 记录一个数据, 这里传的 -1
@Override
public void countLaunchingActivities(int num) {
mNumLaunchingActivities.getAndAdd(num);
}
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
接着看 performLaunchActivity
的实现:
// frameworks/base/core/java/android/app/ActivityThread.java
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
// 反射创建一个 Activity 对象
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
// new 一个 configuration
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
// attach 重点
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
// 走 else
//persistableMode 查看 https://blog.csdn.net/lincyang/article/details/45287599
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortStr ing() +
" did not call through to super.onCreate()");
}
r.activity = activity;
}
r.setState(ON_CREATE);
// updatePendingActivityConfiguration() reads from mActivities to update
// ActivityClientRecord which runs in a different thread. Protect modifications to
// mActivities to avoid race.
synchronized (mResourcesManager) {
mActivities.put(r.token, r);
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
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
重点调用 Activity 的 attach 方法:
// frameworks/base/core/java/android/app/Activity.java
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
// 初始化 PhoneWindow 对象
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
// 初始化 Activity 的成员变量
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mAssistToken = assistToken;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
// 给 PhoneWindow 设置 WindowManager
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
setAutofillOptions(application.getAutofillOptions());
setContentCaptureOptions(application.getContentCaptureOptions());
}
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
回到 executeLifecycleState
中,executeCallbacks 执行完毕后,接着执行 executeLifecycleState
// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
// ......
// 执行回调
// LaunchActivityItem
executeCallbacks(transaction);
// 执行生命周期
// ResumeActivityItem
executeLifecycleState(transaction);
mPendingActions.clear();
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
executeLifecycleState 的实现如下:
// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
// 拿到 ActivityLifecycleItem,这里是子类 ResumeActivityItem
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
// ......
// token 是一个索引值
// 通过 token 可以拿到 ActivityClientRecord,这个对象是 App 端的,用于描述描述一个 Activity
final IBinder token = transaction.getActivityToken();
final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
+ lifecycleItem + " for activity: "
+ getShortActivityName(token, mTransactionHandler));
}
if (r == null) {
// Ignore requests for non-existent client records for now.
return;
}
// Cycle to the state right before the final requested state.
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
// Execute the final transition with proper parameters.
// 执行生命周期
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
// 执行生命周期后的操作也要关心
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
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
接着执行 ResumeActivityItem 的 execute:
// /frameworks/base/core/java/android/app/servertransaction/ResumeActivityIt.java
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
"RESUME_ACTIVITY");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@Override
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
try {
// TODO(lifecycler): Use interface callback instead of AMS.
// 远程调用 ATMS 的 activityResumed
ActivityTaskManager.getService().activityResumed(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
client 的具体类型是 ActivityThread
接着执行到 ActivityThread 的 handleResumeActivity 方法:
// /frameworks/base/core/java/android/app/ActivityThread.java
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
// 关键
// TODO Push resumeArgs into the activity for consideration
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
if (r == null) {
// We didn't actually resume the activity, so skipping any follow-up actions.
return;
}
if (mActivitiesToBeDestroyed.containsKey(token)) {
// Although the activity is resumed, it is going to be destroyed. So the following
// UI operations are unnecessary and also prevents exception because its token may
// be gone that window manager cannot recognize it. All necessary cleanup actions
// performed below will be done while handling destruction.
return;
}
final Activity a = r.activity;
if (localLOGV) {
Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity
+ ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);
}
final int forwardBit = isForward
? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
// If the window hasn't yet been added to the window manager,
// and this guy didn't finish itself or start another activity,
// then go ahead and add the window.
boolean willBeVisible = !a.mStartedActivity;
if (!willBeVisible) {
try {
willBeVisible = ActivityTaskManager.getService().willActivityBeVisible(
a.getActivityToken());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
// Get rid of anything left hanging around.
cleanUpPendingRemoveWindows(r, false /* force */);
// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
if (r.newConfig != null) {
performConfigurationChangedForActivity(r, r.newConfig);
if (DEBUG_CONFIGURATION) {
Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig "
+ r.activity.mCurrentConfig);
}
r.newConfig = null;
}
if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
WindowManager.LayoutParams l = r.window.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
!= forwardBit) {
l.softInputMode = (l.softInputMode
& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
| forwardBit;
if (r.activity.mVisibleFromClient) {
ViewManager wm = a.getWindowManager();
View decor = r.window.getDecorView();
wm.updateViewLayout(decor, l);
}
}
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}
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
接着调用 performResumeActivity:
// /frameworks/base/core/java/android/app/ActivityThread.java
/**
* Resume the activity.
* @param token Target activity token.
* @param finalStateRequest Flag indicating if this is part of final state resolution for a
* transaction.
* @param reason Reason for performing the action.
*
* @return The {@link ActivityClientRecord} that was resumed, {@code null} otherwise.
*/
@VisibleForTesting
public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
String reason) {
final ActivityClientRecord r = mActivities.get(token);
if (localLOGV) {
Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);
}
if (r == null || r.activity.mFinished) {
return null;
}
if (r.getLifecycleState() == ON_RESUME) {
if (!finalStateRequest) {
final RuntimeException e = new IllegalStateException(
"Trying to resume activity which is already resumed");
Slog.e(TAG, e.getMessage(), e);
Slog.e(TAG, r.getStateString());
// TODO(lifecycler): A double resume request is possible when an activity
// receives two consequent transactions with relaunch requests and "resumed"
// final state requests and the second relaunch is omitted. We still try to
// handle two resume requests for the final state. For cases other than this
// one, we don't expect it to happen.
}
return null;
}
if (finalStateRequest) {
r.hideForNow = false;
r.activity.mStartedActivity = false;
}
try {
r.activity.onStateNotSaved();
r.activity.mFragments.noteStateNotSaved();
checkAndBlockForNetworkAccess();
if (r.pendingIntents != null) {
deliverNewIntents(r, r.pendingIntents);
r.pendingIntents = null;
}
if (r.pendingResults != null) {
deliverResults(r, r.pendingResults, reason);
r.pendingResults = null;
}
// 调用 Activity 的 performResume
r.activity.performResume(r.startsNotResumed, reason);
r.state = null;
r.persistentState = null;
r.setState(ON_RESUME);
reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming");
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException("Unable to resume activity "
+ r.intent.getComponent().toShortString() + ": " + e.toString(), e);
}
}
return r;
}
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
调用 Activity 的 performResume:
// /frameworks/base/core/java/android/app/ActivityThread.java
final void performResume(boolean followedByPause, String reason) {
dispatchActivityPreResumed();
performRestart(true /* start */, reason);
mFragments.execPendingActions();
mLastNonConfigurationInstances = null;
if (mAutoFillResetNeeded) {
// When Activity is destroyed in paused state, and relaunch activity, there will be
// extra onResume and onPause event, ignore the first onResume and onPause.
// see ActivityThread.handleRelaunchActivity()
mAutoFillIgnoreFirstResumePause = followedByPause;
if (mAutoFillIgnoreFirstResumePause && DEBUG_LIFECYCLE) {
Slog.v(TAG, "autofill will ignore first pause when relaunching " + this);
}
}
mCalled = false;
// mResumed is set by the instrumentation
// 调用 Activity 的 onResume 生命周期回调方法
mInstrumentation.callActivityOnResume(this);
writeEventLog(LOG_AM_ON_RESUME_CALLED, reason);
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onResume()");
}
// invisible activities must be finished before onResume() completes
if (!mVisibleFromClient && !mFinished) {
Log.w(TAG, "An activity without a UI must call finish() before onResume() completes");
if (getApplicationInfo().targetSdkVersion
> android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
throw new IllegalStateException(
"Activity " + mComponent.toShortString() +
" did not call finish() prior to onResume() completing");
}
}
// Now really resume, and install the current status bar and menu.
mCalled = false;
mFragments.dispatchResume();
mFragments.execPendingActions();
onPostResume();
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onPostResume()");
}
dispatchActivityPostResumed();
}
/**
* Perform calling of an activity's {@link Activity#onResume} method. The
* default implementation simply calls through to that method.
*
* @param activity The activity being resumed.
*/
public void callActivityOnResume(Activity activity) {
activity.mResumed = true;
activity.onResume();
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
am.match(activity, activity, activity.getIntent());
}
}
}
}
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
最后在 postexcute 中会远程调用 ATMS 的 activityResumed 方法:
@Override
public final void activityResumed(IBinder token) {
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) {
ActivityRecord.activityResumedLocked(token);
mWindowManager.notifyAppResumedFinished(token);
}
Binder.restoreCallingIdentity(origId);
}
2
3
4
5
6
7
8
9
至此呢,整个 Activity 启动过程就分析完了。 详细的启动流程示意图可以参考以下链接:
https://boardmix.cn/app/share/CAE.CMLx1wwgASoQRzGM12A9bzXviUBJvfqsPjAGQAE/hxtUlY