Android应用程序启动流程(二)

一、前言

上一篇文章中,我们分析了应用程序进程启动的流程。那么,在应用程序进程已启动的情况下,应用程序又是如何启动的呢?在这篇文章中,我们将从点击应用快捷图标开始,分析应用程序是如何启动的,即根Activity是如何启动的。

二、根Activity启动流程

2.1 Launcher 请求 AMS 过程

还记得Android系统启动流程中,最后一个阶段是什么嘛?没错,是Launcher应用程序的启动,也就是手机的桌面。它是Zygote进程孵化的第一个APP。在启动过程中,它会请求PackageManagerService返回系统中已经安装的应用程序的信息,并将这些信息封装成一个快捷图标列表显示在系统屏幕上,用户可以通过点击图标来启动相应的应用程序。

当我们点击应用图标时,LauncheronClick方法被调用,该方法如下

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
//路径:/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
public void onClick(View v) {
......
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {//应用程序快捷图标
//处理应用程序快捷方式的点击事件
onClickAppShortcut(v);
} else if (tag instanceof FolderInfo) {//文件夹
if (v instanceof FolderIcon) {//点击的视图时文件夹图标
onClickFolderIcon(v);
}
} else if ((FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && v instanceof PageIndicator) ||
(v == mAllAppsButton && mAllAppsButton != null)) {
onClickAllAppsButton(v);
} else if (tag instanceof AppInfo) {//应用信息
startAppShortcutOrInfoActivity(v);
} else if (tag instanceof LauncherAppWidgetInfo) {//Launcher小部件,如天气、日期等小部件
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v);
}
}
}


protected void onClickAppShortcut(final View v) {
//对v的检测
......
// Start activities
startAppShortcutOrInfoActivity(v);
}


private void startAppShortcutOrInfoActivity(View v) {
ItemInfo item = (ItemInfo) v.getTag();
Intent intent = item.getIntent();
if (intent == null) {
throw new IllegalArgumentException("Input must have a valid intent");
}
//startActivitySafely()启动应用程序
boolean success = startActivitySafely(v, intent, item);
//记录应用程序启动的用户事件(日志)
getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115

if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
}


public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
......
//创建一个新的任务栈来启动Activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (v != null) {
intent.setSourceBounds(getViewBounds(v));
}
try {
if (Utilities.ATLEAST_MARSHMALLOW
&& (item instanceof ShortcutInfo)
&& (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
|| item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
&& !((ShortcutInfo) item).isPromise()) {
// Shortcuts need some special checks due to legacy reasons.
startShortcutIntentSafely(intent, optsBundle, item);
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
startActivity(intent, optsBundle);
} else {
LauncherAppsCompat.getInstance(this).startActivityForProfile(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
}
return true;
} catch (ActivityNotFoundException|SecurityException e) {
......
}
return false;
}

如果点击的时应用快捷图标,会调用onClickAppShortcut方法,进而调用startAppShortcutOrInfoActivity方法,获取视图对象的Intent,然后调用startActivitySafely方法,设置IntentFlagFLAG_ACTIVITY_NEW_TASK,指示Android系统通过创建一个新的任务栈来启动Activity,之后会调用startActivity方法,该方法如下

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
//路径:/frameworks/base/core/java/android/app/Activity.java
/**
* Launch a new activity. You will not receive any information about when
* the activity exits. This implementation overrides the base version,
* providing information about the activity performing the launch.
* Because of this additional information,
* the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not
* required; if not specified, the new activity will be added to the
* task of the caller.
*
* @param intent The intent to start.
* @param options Additional options for how the Activity should be started.
*/
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}


/**
* Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
* with no options.
*
* @param requestCode If >= 0, this code will be returned in
* onActivityResult() when the activity exits.
*/
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}


/**
* Launch an activity for which you would like a result when it finished.
* When this activity exits, your
* onActivityResult() method will be called with the given requestCode.
* Using a negative requestCode is the same as calling
* {@link #startActivity} (the activity is not launched as a sub-activity).
*/
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {//当前Activity是否有父Activity
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);
if (ar != null) {
//通过主线程的sendActivityResult方法将结果数据发送给发起请求的Activity
mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}

startActivity方法中,无论哪个分支,最终都会调用三个参数的startActivityForResult方法,第二个参数requestCode = -1表示Launcher不需要知道Activity启动的结果,第三个参数则代表Activity启动的方式。

在三个参数的startActivityForResult方法中,mParentActivity类型的,表示当前Activity的父类。很显然,我们要启动的应用程序的第一个Activity(也就是根Activity)还没有创建出来,所以调用mInstrumentationexecStartActivity方法,mInstrumentation主要用来监控应用程序和系统的交互。execStartActivity方法如下

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
//路径:/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) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
//检查是否存在活动监视器mActivityMonitors
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
//遍历监视器查找匹配的Activity
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
return result;
} else if (am.match(who, null, intent)) {
am.mHits++;
//当该monitor阻塞activity启动,则直接返回
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
//获取AMS的代理对象并调用startActivity方法
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
//检查Activity的启动结果
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}

先通过活动监视器检查正在启动的Activity是否受监视或拦截,如果没有,则调用ActivityManagergetService方法获得AMS的代理对象,接着调用startActivity方法。

首先看getService方法做了什么,该方法如下

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
//路径:/frameworks/base/core/java/android/app/ActivityManager.java
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}


private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};


//路径:/frameworks/base/core/java/android/util/Singleton.java
public abstract class Singleton<T> {
private T mInstance;

protected abstract T create();

public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}

getService方法调用了IActivityManagerSingletonget方法,而IActivityManagerSingleton是一个Singleton类,这个类中get方法调用了create方法。它在创建的时候重写了create方法,通过getService方法获取名为 “activity” 的Service引用,也就是IBinder类型的AMS引用,接着将它转换成IActivityManager类型的对象(采用的是AIDLIActivityManager.java类是由AIDL工具编译IActivityManager.aidl时生成的)。AIDL的作用是实现跨进程通信(IPC),在这里是建立服务端AMS和客户端Launcher之间的通信。

回到Instrumentation.java,接下来是调用startActivity方法。

2.2 AMS 到 ApplicationThread 的调用过程

Launcher请求AMS后,代码逻辑进入到AMS中, AMSstartActivity方法如下

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
//路径:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}



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) {
//判断调用者进程是否被隔离
enforceNotIsolatedCaller("startActivity");
//检查调用者权限
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null,
"startActivityAsUser");
}

startActivity方法相比, startActivityAsUser方法的参数多了一个UserHandle.getCallingUserId(),此方法用于获取调用者的UserId。接着在startActivityAsUser方法中,检查调用者进程是否被隔离,以及调用者权限,最后调用startActivityMayWait方法,该方法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//路径:/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask, String reason) {
......
//创建新的Intent对象,即便intent被修改也不受影响
intent = new Intent(intent);

//收集Intent所指向的Activity信息, 当存在多个可供选择的Activity,则直接向用户弹出resolveActivity
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
......
synchronized (mService) {
......
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask, reason);

......

return res;
}
}


int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask, String reason) {
//判断启动理由是否为空
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;

mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
container, inTask);

if (outActivity != null) {
// mLastStartActivityRecord[0] is set in the call to startActivity above.
outActivity[0] = mLastStartActivityRecord[0];
}
return mLastStartActivityResult;
}


private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle
= options != null ? options.popAppVerificationBundle() : null;

ProcessRecord callerApp = null;
if (caller != null) {
//获得Launcher进程
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
err = ActivityManager.START_PERMISSION_DENIED;
}
}

......
//创建即将要启动的Activity的描述类ActivityRecord
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, container, options, sourceRecord);
if (outActivity != null) {
outActivity[0] = r;
}
......

doPendingActivityLaunchesLocked(false);

return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}

startActivityMayWait方法中,我们主要关注startActivityLocked方法,该方法先判断了一下启动理由,然后调用startActivity方法(怎么这么多同名方法啊!)。该方法中,调用了mService.getRecordForAppLocked(caller)获得代表Launcher进程的callerApp对象,它是ProcessRecord类型的,ProcessRecord用于描述一个应用程序进程。参数caller是一路传过来的,指向的是Launcher所在的应用程序进程的AppliactionThread对象。

同样地,ActivityRecord用于描述一个Activity,记录其所用信息。ActivityRecord方法创建了用于描述将要启动的Activity信息的对象r,并将r赋值给outActivity[0],两者作为startActivity方法的参数传递下去。

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
//路径:/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
int result = START_CANCELED;
try {
//延迟窗口布局的操作
mService.mWindowManager.deferSurfaceLayout();
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
} finally {
if (!ActivityManager.isStartResultSuccessful(result)
&& mStartActivity.getTask() != null) {
mStartActivity.getTask().removeActivity(mStartActivity);
}
//继续执行窗口布局操作
mService.mWindowManager.continueSurfaceLayout();
}

postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
mTargetStack);

return result;
}



private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {

......

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)) {

mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
} else {
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId, preferredLaunchDisplayId, mTargetStack.mStackId);

return START_SUCCESS;
}

startActivity方法调用了startActivityUnchecked方法,该方法主要是处理与Activity栈管理相关的逻辑。在 2.1 中的 startActivitySafely方法,里面设置IntentFlagFLAG_ACTIVITY_NEW_TASK。所以这里会调用setTaskFromReuseOrCreateNewTask方法,创建一个新的TaskRecord用于描述Activity栈。之后会调用resumeFocusedStackTopActivityLocked方法,该方法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//路径:/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
//判断目标Activity栈是否存在,并且目标Activity栈是否为焦点Activity栈(用户当前正在与之交互的任务的Activity栈)
if (targetStack != null && isFocusedStack(targetStack)) {
//恢复焦点Activity栈的顶部活动
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
//获取当前焦点Activity栈的顶部正在运行的Activity
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
//获得到的ActivityRecord为空或者不处于RESUMED状态
if (r == null || r.state != RESUMED) {
//恢复焦点Activity栈的顶部活动
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}

走到这一步,新Activity栈已经创建好了,但是Activity还没创建好,所以调用后一个resumeTopActivityUncheckedLocked方法,该方法如下

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
//路径:/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
//检查是否已经在递归执行resumeTopActivityInnerLocked方法,避免进一步递归调用
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}

boolean result = false;
try {
//防止递归调用,将mStackSupervisor.inResumeTopActivity标志设置为true,表示正在恢复栈顶活动
mStackSupervisor.inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
} finally {
//将mStackSupervisor.inResumeTopActivity标志重新设置为false,表示恢复顶部活动的过程结束
mStackSupervisor.inResumeTopActivity = false;
}

mStackSupervisor.checkReadyForSleepLocked();

return result;
}



private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
......
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}

if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}

resumeTopActivityUncheckedLocked方法中,根据mStackSupervisor.inResumeTopActivity标志来防止递归调用resumeTopActivityInnerLocked方法,之后调用resumeTopActivityInnerLocked方法,该方法代码巨多,主要关注startSpecificActivityLocked方法,该方法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//路径:/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
//获取即将启动的Activity的所在的应用程序进程
ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
//如果要启动的Activity所在的应用程序进程已经运行
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) {
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e);
}
}
//应用程序没有运行或者没有有效的进程线程,调用startProcessLocked方法启动目标活动所属的进程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true);
}

startSpecificActivityLocked方法中,先通过getProcessRecordLocked方法获得即将启动的Activity的所在的应用程序进程,接着判断得到的应用程序进程是否已经运行了,如果没有运行,则调用startProcessLocked方法,沿着此方法继续下去,就是应用程序进程启动流程了。如果运行了,就调用realStartActivityLocked方法,该方法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//路径:/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
......

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);

......
return true;
}

这里的app指传入的要启动的Activity所在的应用程序进程, app.threadIApplicationThread,它的实现是ActivityThread的内部类AppliactionThread,这个类又是继承IApplicationThread.Stub的。

realStartActivityLocked方法主要是调用scheduleLaunchActivity方法,将启动Activity的请求发送给应用程序所在的进程。当前代码逻辑运行在AMS所在的进程(SystemServer进程)中,通过ApplicationThread来与应用程序进程进行Binder通信,即ApplicationThreadAMS所在的进程和应用程序进程的通信桥梁。

2.3 ActivityThread启动Activity的过程

在上一篇文章里讲过,应用程序进程创建后会运行代表主线程的实例ActivityThread,它管理者当前应用程序进程的主线程。 scheduleLaunchActivity方法就是在AppliactionThread类中的,该类又是ActivityThread的内部类。所以代码逻辑终于进入到应用程序进程中。scheduleLaunchActivity该方法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
//更新进程的状态
updateProcessState(procState, false);
//将要启动的Activity的参数封装成ActivityClientRecord
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
......
//更新要要启动Activity的配置
updatePendingConfiguration(curConfig);
//向H类发送类型为LAUNCH_ACTIVITY的消息
sendMessage(H.LAUNCH_ACTIVITY, r);
}

scheduleLaunchActivity方法将传入的参数封装成ActivityClientRecord对象,sendMessage方法向H类发送类型为LAUNCH_ACTIVITY的消息,并将ActivityClientRecord传递过去。sendMessage方法有多个重载方法,调用到的如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}


private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES)
Slog.v(TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj);
//获取消息实例
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
//是否是异步消息
if (async) {
msg.setAsynchronous(true);
}
//调用消息处理程序(mH)的sendMessage方法将消息发送出去
mH.sendMessage(msg);
}

mHH类,它是ActivityThread的内部类并继承自Handler,是应用程序进程中主线程的消息管理类。因为ApplicationThread是一个Binder,它的调用逻辑运行在Binder线程池中,所以这里需要用H类将代码的逻辑切换到主线程中。

sendMessage方法将消息添加到消息队列中,消息处理程序会自动从队列中取出消息并调用对应的handleMessage方法进行处理,该方法在H类中,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
......
}
Object obj = msg.obj;
if (obj instanceof SomeArgs) {
((SomeArgs) obj).recycle();
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}

handleMessageLAUNCH_ACTIVITY消息的处理为:将参数obj(也就是在scheduleLaunchActivity方法中创建的ActivityClientRecord)转成ActivityClientRecord对象,通过getPackageInfoNoCheck的方法获得LoadedApk类型的对象并赋值给r.packageInfo

为什么要获取LoadedApk呢?因为应用程序进程要启动Activity时,需要将该Activity所属的APK加载进来,而LoadedApk就是用来描述已加载的APK文件的。

接下来调用handleLaunchActivity方法,该方法如下

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
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
//取消之前计划的GC(垃圾回收机制)操作,因为应用程序正在重新变为活动状态
unscheduleGcIdler();
mSomeActivitiesChanged = true;
//如果ActivityClientRecord对象中包含了profilerInfo(性能分析器相关信息),则将其设置到mProfiler中,并启动性能分析器
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}

//处理配置变更,确保当前运行时使用的是最新的配置信息
handleConfigurationChanged(null, null);

if (localLOGV)
Slog.v(TAG, "Handling launch of " + r);

//初始化窗口管理器
WindowManagerGlobal.initialize();
//执行Activity启动流程
Activity a = performLaunchActivity(r, customIntent);
//判断Activity是否启动成功
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
//将Activity的状态设置为Resume
handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

if (!r.activity.mFinished && r.startsNotResumed) {
performPauseActivityIfNeeded(r, reason);
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
//停止Activity启动
try {
ActivityManager.getService().finishActivity(r.token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}

取消GC操作,根据profilerInfo决定是否启动性能分析器,然后更新配置,初始化窗口管理器,调用performLaunchActivity方法启动Activity,如果启动成功,则进行相应的处理,包括保存配置信息、报告Activity尺寸配置、将Activity的状态设置为Resume等。如果Activity启动失败,则通知ActivityManager停止当前Activity

接下来看performLaunchActivity方法,该方法如下

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
//路径:/frameworks/base/core/java/android/app/ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//获取Activity的信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE);
}
//获取componentName,即Activity的全限定类名(包名和类名)
ComponentName component = r.intent.getComponent();
......
//启动Activity的上下文环境(Context)
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);
}
}
......

try {
//创建应用程序对象(Application)的实例
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
......

if (activity != null) {
//初始化Activity
......
//对 Activity 进行初始化和连接关键组件
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);

......
//启动Activity
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
......
}
r.paused = true;

mActivities.put(r.token, r);

}
......

return activity;
}

先做一些准备工作,比如获取Activity的信息、获取APK文件描述信息、获取组件名称(ComponentName)、获取上下文环境(Context)。然后调用mInstrumentationnewActivity方法,通过类加载器创建Activity实例。

接着是调用makeApplication方法创建应用程序对象(Application)的实例。在 Android 中,每个应用程序都有一个全局的 Application 对象,该对象在整个应用程序的生命周期中存在,并且可以用于存储和共享应用程序的全局状态和数据。

之后是对刚创建的Activity实例进行初始化工作,最后调用callActivityOnCreate方法启动Activity。该方法如下

1
2
3
4
5
6
7
8
9
//路径:/frameworks/base/core/java/android/app/Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState) {
//执行预处理操作,例如设定主题样式、初始化资源等
prePerformCreate(activity);
//执行Activity的创建操作
activity.performCreate(icicle, persistentState);
//执行后处理操作,例如注册广播接收器、初始化数据等
postPerformCreate(activity);
}

关键是调用了ActivityperformCreate方法,该方法如下

1
2
3
4
5
6
7
8
9
10
11
//路径:/frameworks/base/core/java/android/app/Activity.java
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
//在Android 6.0及以上版本中,应用需要动态请求某些权限,该方法用于恢复之前的权限请求状态
restoreHasCurrentPermissionRequest(icicle);
//调用Activity的实际的onCreate方法,执行开发者在Activity中重写的onCreate方法
onCreate(icicle, persistentState);
//读取Activity的转场状态,即过渡动画的状态。这个方法将之前保存的转场状态恢复到当前Activity中
mActivityTransitionState.readState(icicle);
//执行一些通用的初始化操作
performCreateCommon();
}

performCreate方法中会调用Activity的实际的onCreate方法,其具体的实现是由开发者来重写。到此,根Activity就启动了,即应用程序启动了。

三、总结

整个流程下来非常长,感觉有点杂乱,这里简单梳理一下整个应用程序启动的流程(假设应用程序进程没有运行):

  1. 点击桌面的应用图标,Launcher进程使用BinderSystemServer进程的AMS进行跨进程通信(IPC),发起startActivity请求。
  2. SystemServer进程的AMS接收到请求后,通过zygoteSendArgsAndGetResultzygote进程进行Socket通信,发送创建进程的请求。
  3. Zygote进程接收请求后,通过forkAndSpecialize方法创建应用程序进程,然后进行一系列初始化工作。
  4. 启动了应用程序进程后,AMS通过ApplicationThread来与应用程序进程进行Binder通信,发送scheduleLaunchActivity请求。
  5. 应用程序进程的Binder线程(ApplicationThread)接收到请求后,通过sendMessage方法与主线程ActivityThread进行Handler通信,发送 LAUNCH_ACTIVITY的消息。
  6. 主线程ActivityThread接收到消息后,通过反射机制创建目标Activity,并回调Activity.onCreate()等方法。到此,应用程序便正式启动,开始进入Activity生命周期。

参考:

Android深入四大组件(一)应用程序启动过程(前篇) | BATcoder - 刘望舒 (liuwangshu.cn)

Android深入四大组件(一)应用程序启动过程(后篇) | BATcoder - 刘望舒 (liuwangshu.cn)

startActivity启动过程分析 - Gityuan博客 | 袁辉辉的技术博客

死磕Android_App 启动过程(含 Activity 启动过程) - 知乎 (zhihu.com)


Android应用程序启动流程(二)
http://example.com/2023/07/24/Android安全/Android应用程序启动流程(二)/
作者
gla2xy
发布于
2023年7月24日
许可协议