启动流程
MoMo Lv5

Activity启动流程

image

Activity.startActivity—> startActivityForUser –>Instrumentation.excuStartActivity–>ATM —startActivity
->判断 需要启动的 Activity 所在的进程 是否已经启动
->如果启动了 realStartActivityLocked
进程不存在:mService.startProcessAsync
-> AMS 如何通知到 zygote
—>zygote 如何创建 应用进程的 ===system server 创建一样流程一样的

  1. 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;
  2. system_server进程接收到请求后,向zygote进程发送创建进程的请求;
  3. Zygote进程fork出新的子进程,即App进程;
  4. App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
  5. system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
  6. App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
  7. 主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。

到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面

init.cpp#main() -> LoadBootScripts(actionManager, serviceList) -> 解析init.rc -> trigger zygote-start

Launcher进程请求AMS

根Activity的启动流程就是桌面上点击一个应用图标进入到应用的第一个Activity的流程,桌面可以看成一个程序,即Launcher。

当系统开机后,Launcher也随之被启动,然后将已经安装的应用程序图标显示到桌面上,当点击一个应用图标其实就是相当于点击活动中的一个button,其相应事件就是Launcher进程请求AMS来启动该应用程序。

image

请求的入口就是Launcher的startActivitySafe方法:
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
...
// 根Activity会在新的任务栈中启动
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

try {
...
if (isShortcut) {
startShortcutIntentSafely(intent, optsBundle, item);
} else if (user == null || user.equals(Process.myUserHandle())) {
// 调用startActivity
startActivity(intent, optsBundle);
} else {
LauncherAppsCompat.getInstance(this).startActivityForProfile(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
}
...
return true;
} catch (ActivityNotFoundException|SecurityException e) {
...
}
return false;
}

该方法为根Activity设置了flag,即根Activity会在新的任务栈中启动。

frameworks/base/core/java/android/app/Activity.java

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
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
//第二个参数为-1表示Launcher不需要知道根Activity的启动结果
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}


public void startActivityForResult(
@RequiresPermission Intent intent,
int requestCode,
@Nullable Bundle options
) {
//mParent表示当前Activity的父类,当根活动还没创建则mParent==null
if (mParent == null) {
options = transferSpringboardActivityOptions(options);

// 1
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...
}
...
}

每个Activity都持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象

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
// frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity(
Context who,
IBinder contextThread,
IBinder token,
Activity target,
Intent intent, int requestCode, Bundle options
) {
...
try {
...
//获取AMS的代理对象
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}


@UnsupportedAppUsage
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}

@UnsupportedAppUsage
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
//得到activity的service引用,即IBinder类型的AMS引用
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//转换成IActivityManager对象
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};

在Singleton中的create方法中由于b是AMS引用作为服务端处于SystemServer进程中,与当前Launcher进程作为客户端与服务端不在同一个进程,所以am返回的是IActivityManager.Stub的代理对象,此时如果要实现客户端与服务端进程间的通信,只需要在AMS继承了IActivityManager.Stub类并实现了相应的方法,这样Launcher进程作为客户端就拥有了服务端AMS的代理对象,然后就可以调用AMS的方法来实现具体功能了,就这样Launcher的工作就交给AMS实现

AMS发送创建应用进程请求

image

AMS将请求任务转移给Process

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
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public final int startActivity(
IApplicationThread caller,
String callingPackage,
int requestCode,
int startFlags,
ProfilerInfo profilerInfo,
Bundle bOptions) {
return startActivityAsUser(...);
}

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(...)
.setMayWait(userId)
.execute();

}

ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}

startActivity方法经过多个方法调用会去执行startActivityAsUser方法,在startActivityAsUser方法最后会返回mActivityStartController的一长串链式调用方法

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
int execute() {
try {
if (mRequest.mayWait) {
return startActivityMayWait(...);
} else {
return startActivity(...);
}
} finally {
onExecutionComplete();
}
}

private int startActivityMayWait(...) {
.....
// 根据intent在系统中找到合适的应用的activity,如果有多个activity可选择,
// 则会弹出ResolverActivity让用户选择合适的应用。
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);


int res = startActivity(...);
....

}

private int startActivity(...) {
...
result = startActivityUnchecked(...);
...

postStartActivityProcessing(r, result, mTargetStack);

return result;
}

private int startActivityUnchecked(...) {
...
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
//创建新的TaskRecord
result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
setTaskToCurrentTopOrCreateNewTask();
}
...

if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
...
} else {
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
...
}

在startActivityAsUser的链式方法中我们调用了setMayWait这个方法,所以这里的mRequest.mayWait为true,故会继续调用startActivityMayWait方法。

startActivityMayWait方法经过调用多次的startActivity方法后会调用到startActivityUnchecked这个方法,会根据启动标志位和Activity启动模式来决定如何启动一个Activity以及是否要调用deliverNewIntent方法通知Activity有一个Intent试图重新启动它。

无论以何种模式启动最终都会调用ActivityStackSupervisor.resumeFocusedStackTopActivityLocked方法。

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
void startSpecificActivityLocked(
ActivityRecord r,
boolean andResume,
boolean checkConfig
) {
//获取即将要启动的Activity的所在的应用程序进程
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
//如果应用进程已经存在
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.
}
//应用进程还未创建,则通过AMS调用startProcessLocked向Zygote进程发送请求
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);
}

在方法中首先获取到了即将要启动的Activity所在的应用进程,假如是普通的Activity的启动流程的活,这个进程肯定是存在的,所以将执行realStartActivityLocked的方法。但是我们现在讨论的是根Activity的启动流程,由于应用都还未启动,意味着根Activity所在的应用进程还未创建,而mService其实就是AMS,所以这里将调用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
59
60
61
62
63
    private final boolean startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
...

int uid = app.uid; //创建应用进程的用户ID
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
...

/*
* 对用户组进行创建和赋值
*/
if (ArrayUtils.isEmpty(permGids)) {
gids = new int[3];
} else {
gids = new int[permGids.length + 3];
System.arraycopy(permGids, 0, gids, 3, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));

// Replace any invalid GIDs
if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];
if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2];
}
...
//这个参数后文会提到
final String entryPoint = "android.app.ActivityThread";

return startProcessLocked(...);
}
private boolean startProcessLocked(...) {
....
//重点关注
final ProcessStartResult startResult = startProcess(...);

...
}

private ProcessStartResult startProcess(...) {
....
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 {
//通过Process.start方法来为应用创建进程
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);
}
}

在startProcess方法里将调用Process.start来发送应用创建进程的请求。这样AMS就将发送请求的事交给了Process

Process向Zygote进程发送创建应用进程请求

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
public static final ProcessStartResult start(...) {
return ZYGOTE_PROCESS.start(...);
}

public final Process.ProcessStartResult start(...) {
try {
//重点关注
return startViaZygote(...);
} catch (ZygoteStartFailedEx ex) {
}
}

private Process.ProcessStartResult startViaZygote(...) throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<String>();

// --runtime-args, --setuid=, --setgid=,
//创建字符串列表argsForZygote,并将启动应用进程的启动参数保存在这个列表中
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("--runtime-flags=" + runtimeFlags);
if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
argsForZygote.add("--mount-external-default");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
argsForZygote.add("--mount-external-read");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
argsForZygote.add("--mount-external-write");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

...
synchronized(mLock) {
//重点关注
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
useBlastulaPool,
argsForZygote);
}
}

在startViaZygote中会创建字符串列表argsForZygote来保存将要创建的应用进程的启动参数,然后最后会调用zygoteSendArgsAndGetResult方法,而在这个方法中第一个参数会调用openZygoteSocketIfNeeded方法,第三个参数就是启动参数列表。

拓扑排序

视频讲解

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
public static startupSortStore sort(List<? extends startup<?>>startupList){
//入度表
Map<Class<? extends startup>, Integer>inDegreeMap= new HashMap<>();
//0度表
Deque<Class<? extends Startup>>zeroDeque = new ArrayDeque<>();
//任务表 用于保存原图
Map<Class<? extends Startup>,Startup<?>> startupMap = new HashMap<>();
//任务依赖表
Map<Class<? extends startup>, List<Class<? extends Startup>>> startupchildrenMap = new HashMap<>();

// 1.找出图中入度数为0的节点填表的过程
for(startup<?>startup :startupList){
startupMap.put(startup.getClass(),startup);
//记录每个任务的入度数(依赖的任务数)
int dependenciesCount=startup.getDependenciesCount();
inDegreeMap.put(startup.getclass(),dependenciescount);
//记录入度数(依赖的任务数)为0的任务
if(dependenciesCount==0) {
zeroDeque.offer(startup.getclass());
} else {
//遍历本任务的依赖任务,生成任务依赖表
for(Class<? extends startup<?>>parent : startup.dependencies()){
List<Class<? extends startup>>children = startupchildrenMap.get(parent);
if(children == null){
children = new ArrayList<>();
//记录这个父任务的所有子任务
startupchildrenMap.put(parent,children);
}
children.add(startup.getclass());
}
}
}

// 2.删除图中入度为0的这些顶点,并更新全图,,最后完成排序
List<Startup<?>>result = new ArrayList<>();
//处理入度为0的任务
while(!zeroDeque.isEmpty()) {
Class<?extends startup>cls =zeroDeque.poll();
Startup<?>startup =startupMap.get(cls);result.add(startup);
//删除此入度为0的任务
if(startupChildrenMap.containsKey(cls)){
List<Class<? extends startup>>childstartup = startupchildrenMap.get(cls);
for(Class<?extends startup>childcls :childstartup){
Integer num=inDegreeMap.get(childcls);
inDegreeMap.put(childcls,num-1);
if(num-1==0){
zeroDeque.offer(childcls);
}
}
}
}

return new StartupSortStore(result, startupMap, startupchildrenMap);
}
Powered by Hexo & Theme Keep
Unique Visitor Page View