【Android 13源码分析】Activity启动流程-3

对WMS很感兴趣,所以决定以在桌面点击应用图标,到应用的Activity显示到屏幕上,这一简单操作为基础,分析整个过程。

其中涉及到非常多的模块,但是首先需要分析的就是Activity的启动流程,由于篇幅原因,分为以下3部分:

【Android 13源码分析】Activity启动流程-1

【Android 13源码分析】Activity启动流程-2

【Android 13源码分析】Activity启动流程-3

虽然整个操作实际上就2S时间,但是整个完整的流程分析下来也需要几个月,而且还是仅仅是启动主流程,

这三篇对Activity启动流程分析只关心主流程,不看具体细节,当然对于一些关键方法会着重介绍,这样以后如果有遇到相关问题的修改可以通过这篇笔记找到具体代码位置,然后根据具体的问题分析修改。

后续会有在Activity启动流程基础上延伸出来的各个分支的记录,比如窗口的创建与挂载,Surface相关,窗口的动画等待,这些流程的分析都需要基于Activity启动流程。

启动Activity的方式有很多,当前以在Launch中点击“电话”图标启动应用为例,本篇为Activity启动的第三篇, 主要是在目标应用进程启动后的逻辑。

  1. 应用进程创建

java的方法的main函数
其实在执行到AMS::attachApplication前,应用进程也有一段逻辑

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
java复制代码# ActivityThread
// ApplicationThread 是 AMS 作为 C 端时,与应用进程通信的方式
final ApplicationThread mAppThread = new ApplicationThread();
public static void main(String[] args) {
......
// 重点 *1. 主线程Looper 处理已经创建ActivityThread
// 主线程Looper
Looper.prepareMainLooper();
......
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
// 主线程Looper
Looper.loop();
}
private void attach(boolean system, long startSeq) {
......
final IActivityManager mgr = ActivityManager.getService();
try {
//重点 *2. 将mAppThread告知AMS,用于AMS与应用进程通信
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
......
}

应用进程(电话)创建完毕后,在main方法里会执行attach,就是要将自己的信息告知AMS,毕竟AMS 是管理模块。

  1. AMS收到“电话”进程创建完毕的执行 realStartActivityLocked

因为进程创建也不是由AMS执行,AMS也不知道具体什么时候进程创建好了,所以在应用进程创建好后,会执行 AMS::attachApplication来告知。 这样就可以AMS就知道可以开始处理后续逻辑了

2.1 调用链

1
2
3
4
5
6
7
8
9
10
11
arduino复制代码AMS::attachApplication
AMS::attachApplicationLocked
ActivityThread::bindApplication
ActivityTaskManagerService.LocalService::attachApplication
WindowContainer::forAllRootTasks --- 省略forAllRootTasks等固定堆栈
Task::forAllRootTasks
WindowContainer::forAllActivities
ActivityRecord::forAllActivities
RootWindowContainer.AttachApplicationHelper::test
RootWindowContainer.AttachApplicationHelper::test
ActivityTaskSupervisor::realStartActivityLocked -- 构建LaunchActivityItem

调用链realStartActivityLocked.png

接上一篇知道如果进程启动了ActivityTaskSupervisor::startSpecificActivity就会走进去ActivityTaskSupervisor::realStartActivityLocked。
但是可能会好奇怎么就知道要执行应用MainActivity到onCreate就一定是在这个方法里呢? 调试方法有很多,比如加log,打堆栈,但是对应这个逻辑比较简单的是,需要执行Activity启动到onCreate的控制在LaunchActivityItem中,而LaunchActivityItem在framework的引用出了本身,就只有在ActivityTaskSupervisor。

为什么看ActivityTaskSupervisor.png

2.2 主流程

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
scss复制代码# AMS 
// 当应用进程调用attachApplication 执行
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
// 获取 应用进程的信息后执行attachApplicationLocked
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// 需要启动应用的进程数据
ProcessRecord app;
......
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
// 通过mPidsSelfLocked获取
app = mPidsSelfLocked.get(pid);
}
......
}
......
// 触发ActivityThread::bindApplication 逻辑
if (app.getIsolatedEntryPoint() != null) {

} else if (instr2 != null) {
// bindApplication
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
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 (normalMode) {
try {
// 重点 触发构建 LaunchActivityItem 流程
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
......
}

这里是触发 LaunchActivityItem 的流程主线 , mAtmInternal是 ATMS 的内部类 LocalService

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
java复制代码# ActivityTaskManagerService.LocalService
@Override
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
......
return mRootWindowContainer.attachApplication(wpc);
......
}
# RootWindowContainer
boolean attachApplication(WindowProcessController app) throws RemoteException {
try {
return mAttachApplicationHelper.process(app);
} finally {
mAttachApplicationHelper.reset();
}
}
# RootWindowContainer.AttachApplicationHelper
boolean process(WindowProcessController app) throws RemoteException {
mApp = app;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
// 重点* 调用每个容器的 forAllRootTasks
getChildAt(displayNdx).forAllRootTasks(this);
if (mRemoteException != null) {
throw mRemoteException;
}
}
......
}

这里的重点是执行了forAllRootTasks,当孩子是RootTask容器的时候才会执行Lambda表达式的内容。

AttachApplicationHelper 必然实现了 Consumer 接口, 直接看其 accept 实现即可

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
java复制代码# RootWindowContainer.AttachApplicationHelper
private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {
......
boolean process(WindowProcessController app) throws RemoteException {
mApp = app;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
// 重点*1. 调用每个容器的 forAllRootTasks
getChildAt(displayNdx).forAllRootTasks(this);
if (mRemoteException != null) {
throw mRemoteException;
}
}
......
}
@Override
public void accept(Task rootTask) {
......
// 执行 topRunningActivity
mTop = rootTask.topRunningActivity();
// 重点*2. 执行accept 让容器下的每个 ActivityRecord 执行
rootTask.forAllActivities(this);
}
@Override
public boolean test(ActivityRecord r) {
......
try {
// 重点*3. 执行 realStartActivityLocked 触发创建LaunchActivityItem
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;
}
}

重点分析:
AttachApplicationHelper 实现类Consumer,Predicate接口。 对应要实现的函数分别为accept和test

  1. RootWindowContainer 的 child 自然是 WindowContainer

这里可能有个疑问就是 forAllRootTasks 一个参数的方法有2个重载,参数分别为Consumer 接口和Predicate 接口。 当前的AttachApplicationHelper类这两个都实现了,
怎么判断执行的是哪个呢?
答案也很简单, 只要看一下泛型参数即可。
2. 根据上面的解释, 第二步执行 accept回调, 内部执行 Task::forAllActivities 函数, 但是Task本身没有该方法, 该方法定义在父类 WindowContainer 中

  1. 那么逻辑就来到了气到的realStartActivityLocked ,其内部会构建 LaunchActivityItem,这个在【Activity生命周期事务执行逻辑】有详细说明
    在把 ActivityTaskSupervisor::realStartActivityLocked方法看一下,现在已知 setLifecycleStateRequest为ResumeActivityItem
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
scss复制代码# ActivityTaskSupervisor 

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
// 重点* 判断是否执行完了pause 。 也就是2个条件之一,必须要执行完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;
}
......
// 重点*1. 创建Activity启动事务.
final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.token);
// 判断Activity是否处于向前转场状态
final boolean isTransitionForward = r.isTransitionForward();
// 获取Activity所在 TaskFragment Token
final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
// 重点*2. 将构建的 LaunchActivityItem 添加到 clientTransaction 中
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(), r.compat,
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));
// 重点*3. 设置预期的最终状态
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
// Resume逻辑,启动走的这。 表示需要执行到onCreate
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
} else {
// Pause 逻辑
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// 重点*4. 调度事务,将clientTransaction添加到生命周期管理器中
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
}

2.2.1 LaunchActivityItem handleLaunchActivity (启动ActivityonCreate)

2.2.1.1 调用链

1
2
3
4
5
6
7
8
9
10
arduino复制代码LaunchActivityItem::execute
ActivityThread::handleLaunchActivity
ActivityThread::performLaunchActivity
Instrumentation::newActivity --- 创建Activity
Activity::attach ---处理Window相关
Window::init
Window::setWindowManager
Instrumentation::callActivityOnCreate ---onCreate流程
Activity::performCreate
Activity::onCreate --over

2.2.1.2 主流程

接下来看 LaunchActivityItem::execute

1
2
3
4
5
6
7
8
9
10
11
12
csharp复制代码# LaunchActivityItem 
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
mTaskFragmentToken);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

这里的 client 是 ClientTransactionHandler 类型, 而 ActivityThread 是 ClientTransactionHandler子类

重点是这边创建了ActivityClientRecord,第一个参数就是我们要找的token

逻辑来到应用进程 ActivityThread

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
scss复制代码# ActivityThread

public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
......
final Activity a = performLaunchActivity(r, customIntent);
......
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity activity = null;
try {
// 重点* 1. 通过Instrumentation 反射创建Activity
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
......
}
try {
......
// 重点* 2. 执行 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.activityConfigCallback,
r.assistToken, r.shareableActivityToken);
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
重点* 3. OnCreate流程
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
......
}

# Instrumentation
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
// onCreate流程
activity.performCreate(icicle);
postPerformCreate(activity);
}
# Activity
final void performCreate(Bundle icicle) {
performCreate(icicle, null);
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
......
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
// 执行onCreate
onCreate(icicle);
}
......
}

写过应用的都知道,默认都是一个参数的onCreate。
流程结束

tip:在添加回调的时候,还加了个请求的生命周期, 因为 LaunchActivityItem 只是创建,但是创建完成后,需要执行到对应的生命周期。
正常情况都是希望执行到onResume,所以会设置 ResumeActivityItem,不过不是分析重点,可自行了解

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%