android 应用启动过程

首先,手机中的主页面、以及显示各个应用图标的页面本身就是一个 Activity
android 应用启动就是我们点击应用图标后的过程

以下以 API28 为例

应用启动涉及 L:三个进程、六个大类

三个进程:
Launcher 进程:整个 App 启动流程的起点,负责接收用户点击屏幕事件,它其实就是一个 Activity,里面实现了点击事件,长按事件,触摸等事件,可以这么理解,把 Launcher 想象成一个总的 Activity,屏幕上各种 App 的 Icon 就是这个 Activity 的 button,当点击 Icon 时,会从 Launcher 跳转到其他页面。

SystemServer 进程:这个进程在整个的 Android 进程中是非常重要的一个,地位和 Zygote 等同,它是属于 Application Framework 层的,Android 中的所有服务,例如 AMS, WindowsManager, PackageManagerService 等等都是由这个 SystemServer fork 出来的。

App 进程:你要启动的 App 所运行的进程。

六个大类:
ActivityManagerService:(AMS)AMS 是 Android 中最核心的服务之一,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块相类似,因此它在 Android 中非常重要,它本身也是一个 Binder 的实现类。

Instrumentation:监控应用程序和系统的交互。

ActivityThread:应用的入口类,通过调用 main 方法,开启消息循环队列。ActivityThread 所在的线程被称为主线程。

ApplicationThread:ApplicationThread 提供 Binder 通讯接口,AMS 则通过代理调用此 App 进程的本地方法。

ActivityManagerProxy:AMS 服务在当前进程的代理类,负责与 AMS 通信。

ApplicationThreadProxy:ApplicationThread 在 AMS 服务中的代理类,负责与 ApplicationThread 通信。

可以说,启动的流程就是通过这六个大类在这三个进程之间不断通信的过程。

LauncherActivity

package android.app;

LauncherActivity 既是显示所有应用图标的系统页面
LauncherActivity 布局是一个 ListView

listView 的数据集就是 所有应用的数据集合,每个应用信息为 ListItem

ListItem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static class ListItem {
public ResolveInfo resolveInfo;
public CharSequence label;
public Drawable icon; // 图标
public String packageName; // 应用包名
public String className; // 启动Activity的类名
public Bundle extras;

ListItem(PackageManager pm, ResolveInfo resolveInfo, IconResizer resizer) {
this.resolveInfo = resolveInfo;
label = resolveInfo.loadLabel(pm);
ComponentInfo ci = resolveInfo.activityInfo;
if (ci == null) ci = resolveInfo.serviceInfo;
if (label == null && ci != null) {
label = resolveInfo.activityInfo.name;
}

if (resizer != null) {
icon = resizer.createIconThumbnail(resolveInfo.loadIcon(pm));
}
packageName = ci.applicationInfo.packageName;
className = ci.name;
}
}

而 ListView 涉及的所有信息信息是在 Adapter 的构造函数中获取的,
也就是说其实在启动 LauncherActivity 时,已经获取到所有应用信息

接下来查看 Item 的点击事件,即启动应用的逻辑。

1
2
3
4
5
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = intentForPosition(position);
startActivity(intent);
}

此时就会进入到 Activity 的 startActivity,最后会进入 Activity 的下列方法中:
requestCode: -1 options: null
是在系统页面开启另一个应用,所以 mParent = null

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
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}

cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}

此时会进入 Instrumentation.java 中的 execStartActivity 函数(7 个参数的)
然后又会调用到

1
2
3
4
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target, requestCode, 0, null, options);

又会调用到 ActivityManagerService 中的 startActivity
然后会调用到 ActivityManagerService 中的 startActivityAsUser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
boolean validateIncomingUser) {
enforceNotIsolatedCaller("startActivity");

userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

// TODO: Switch to user app stacks here.
return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();

}

此处使用构建者模式,execute 执行的是 ActivityStarter.java 中的 execute 函数

而最终会调用到 1193 行的 startActivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
...
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
...
return result;
}
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {

...
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
...

return START_SUCCESS;
}

会执行 ActivityStackSupervisor 中的 resumeFocusedStackTopActivityLocked

1
2
3
4
5
6
7
8
9
10
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

...

if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
...
}

然后又会执行到 ActivityStack 中的 resumeTopActivityUncheckedLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
result = resumeTopActivityInnerLocked(prev, options);
...
return result;
}

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {

...
mStackSupervisor.startSpecificActivityLocked(next, true, false);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}

又会回到 ActivityStackSupervisor 中的 startSpecificActivityLocked 函数

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
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);

getLaunchTimeTracker().setLaunchTime(r);

if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}

// If a dead object exception was thrown -- fall through to
// restart the application.
}

mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}

此时会通过 AMS 获取进程信息,判断进程是否存在,
应用进程存在时会调用 realStartActivityLocked
应用进程不存在时会调用 AMS 中的 startProcessLocked 去开启新进程

暂时先看 应用进程不存在的情景:

AMS startProcessLocked

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
@GuardedBy("this")
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */);
}

@GuardedBy("this")
private final boolean startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr, String abiOverride) {
return startProcessLocked(app, hostingType, hostingNameStr,
false /* disableHiddenApiChecks */, abiOverride);
}
private final boolean startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
...
return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
startTime);
}
@GuardedBy("this")
private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
requiredAbi, instructionSet, invokeWith, app.startTime);
...
}

private ProcessStartResult startProcess(String hostingType, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
final ProcessStartResult startResult;
if (hostingType.equals("webview_service")) {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
}
checkTime(startTime, "startProcess: returned from zygote!");
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}

然后会调用 Process 中 start 去开启进程
同时注意,此处会判断进程类型, webview

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
return zygoteProcess.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}

然后又会调用到 ZygoteStartFailedEx 中的 start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  public final Process.ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
...
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
zygoteArgs);
}

private Process.ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
boolean startChildZygote,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}


@GuardedBy("mLock")
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
// Throw early if any of the arguments are malformed. This means we can
// avoid writing a partial response to the zygote.
int sz = args.size();
for (int i = 0; i < sz; i++) {
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}

/**
* See com.android.internal.os.SystemZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;

writer.write(Integer.toString(args.size()));
writer.newLine();

for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}

writer.flush();

// Should there be a timeout on this?
Process.ProcessStartResult result = new Process.ProcessStartResult();

// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();

if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}

最终执行 zygoteSendArgsAndGetResult 函数来完成进程的创建。
注意:
Android 中有一个重要的进程 Zygote,翻译为受精卵进程,所有的应用程序进程都是通过 Zygote 进程 fork 得来的。

简单来说就是通过 Binder 请求 AMS 进程,然后 AMS 再发送 Socket 消息给 Zygote 进程,最后统一由 Zygote 进程 fork 出应用进程。

当进程创建完成后,会执行 ActivityThread 中的 main 方法

在 ActivityThread 中就会启动 消息分发 、 Application 的创建、Activity 的创建