文章参考:https://www.jianshu.com/p/b78a38c857e8

概述

Activity启动流程中设计到的重点类:

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
Instrumentation.java 
// 负责调用Activity和Application生命周期。

ActivityTaskManagerService.java
// 负责Activity管理和调度等工作。android10中新增的

ActivityManagerService.java
//负责管理四大组件和进程,包括生命周期和状态切换。

ActivityTaskManagerInternal.java
//ActivityTaskManagerService对外提供的一个抽象类,真正的实现在ActivityTaskManagerService#LocalService

ActivityThread.java
//Activity线程:管理应用程序进程中主线程的执行.


ActivityStackSupervisor.jaba
//Activity栈管理者:负责所有Activity栈的管理

TransactionExecutor.java
// 事务处理器:主要作用是执行ClientTransaction

ClientLifecycleManager.java
// 客户端生命周期管理器:生命周期的管理调用

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

我们重点学习一下Activity的启动流程,有助于我们理解Activity的是怎么启动起来的。本文基于Android 10版本源码,从Activity启动方法startActivity为切入口分析整个流程。

图片来源于网络。

我们先从一个最简单的方法:

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\Activity.java

@Override
public void startActivity(Intent intent) {
// 调用重载方法,startActivity(intent,bundle)
this.startActivity(intent, null);
}

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {

//第二个参数为-1表示不需要知道Activity的启动结果
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}

我们可以看到,调用了两个重载方法之后,调到了startActivityForResult(Intent intent, int requestCode,Bundle options)

这个方法。这个方法其实就是比startActivity多了requestCode这个参数,这个参数如果我们设置为>=0.
那么这个Activity退出的时候会回调onActivityResult。这里我们先不重点关注。

下面我们看一下startActivityForResult的实现

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
/**
* 启动一个您想要完成的Activity。
* @param intent The intent to start.
* @param requestCode If >= 0, this code will be returned in
* onActivityResult() when the activity exits.
* 这个方法其实就是比startActivity多了requestCode这个参数,这个参数如果我们设置为>=0.
* 那么这个Activity退出的时候会回调onActivityResult。这里我们先不重点关注
* @param options Activity启动的配置选项See {@link android.content.Context#startActivity(Intent, Bundle)}
* @throws android.content.ActivityNotFoundException
*
* @see #startActivity
*/
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
// 如果是第一次启动,那么mParent == null 我们先默认第一次,看下面的代码
// TODO parent被赋值的时候,是什么时候??
if (mParent == null) {
//
options = transferSpringboardActivityOptions(options);

// mInstrumentation 执行启动Activity.这个Instrumentation是Activity的成员变量
// 可以作为我们Hook技术的Hook点。用代理的Instrumentation来替代原始的Instrumentation
// 参数介绍:
// 参数一:Context 上下文对象
/// 参数二:mMainThread.getApplicationThread() 这个参数的是一个Binder对象,
// 是ActivityThread里面的getApplicationThread()
// 参数三:mToken。这个方法页面重要。是客户端Activity与服务端AMS交互的令牌Token
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 {
// 如果mParent不为null.则会调用startActivityFromChild
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);
}
}
}

通过startActivity来启动Activity最终都会调用startActivityForResult来启动,如果是第一次启动,mParent会null,会直接调用Instrumentation#execStartActivity,否则会调用Activity#startActivityFromChild

我们通过跟踪代码,会发现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
int requestCode) {
startActivityFromChild(child, intent, requestCode, null);
}

public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
int requestCode, @Nullable Bundle options) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, child,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, child.mEmbeddedID, requestCode,
ar.getResultCode(), ar.getResultData());
}
cancelInputsAndStartExitTransition(options);
}

其实startActivityFromChild最终也是调用Instrumentation#execStartActivity来启动。

这里,就引出我们一个非常重要的对象Instrumentation

Instrumentation

1
2
3
4
5
6
7
8
9
10
11
12
/**
*@see https://developer.android.com/reference/android/app/Instrumentation
* https://developer.android.google.cn/guide/topics/manifest/instrumentation-element

* Instrumentation 顾名思义,仪表盘。他其实就是检测应用程序代码的基类
* 实际上当启动一个app的时候都会实例化一个Instrumentation对象,
* 且Instrumentation在每个Activity跳转的时候都会用到且其内部类ActivityMonitor会监控activity的。
* 从而使您可以监视系统与应用程序之间的所有交互。
*/
public class Instrumentation {

}

Instrumentation 顾名思义,仪表盘。他其实就是检测应用程序代码的基类
实际上当启动一个app的时候都会实例化一个Instrumentation对象, 且Instrumentation在每个Activity跳转的时候都会用到且其内部类ActivityMonitor会监控activity的。 从而使您可以监视系统与应用程序之间的所有交互。

那么Activit中的Instrumentation是什么时候实例化的呢。我们通过源码可以看到。在Activity的attach()方法里面会传入Instrumentation对象。

看起来,貌似和我们的主流程逻辑没啥关系。但是为什么这里会重点提一下呢?

其实,如果我们了解过插件化的相关知识的时候,就会知道mInstrumentation 执行启动Activity.这个Instrumentation是Activity的成员变量,可以作为我们Hook技术的Hook点。用代理的Instrumentation来替代原始的Instrumentation

好啦。我们继续分析源码

1
2
3
4
5
6
7
8
9
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, child,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, child.mEmbeddedID, requestCode,
ar.getResultCode(), ar.getResultData());
}

通过startActivity来启动Activity最终都会调用startActivityForResult来启动,如果是第一次启动,mParent会null,会直接调用Instrumentation#execStartActivity,否则会调用Activity#startActivityFromChild,最终也是调用Instrumentation#execStartActivity来启动。

Instrumentation#execStartActivity

我们来看Instrumentation#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
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
// 获取ApplicationThread
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
//Instrumentation的监控机制的相关逻辑,我们忽略
if (mActivityMonitors != null) {
// ······省略部分代码
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
// 重点在这里:这里是一个IPC的调用,IActivityTaskManager的服务端是ActivityTaskManagerService,
// 所以ActivityTaskManager.getService().startActivity实际上是
/// 跨进程调用ActivityManagerService启动Activity
// 之后就会在是ActivityTaskManagerService中去执行Activity 的启动流程。
// 注意:这个地方和Android之前版本的逻辑已经不一致了。之前都是直接ActivityManager.getService()
int result = ActivityTaskManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
// 在 checkStartActivityResult 中会检查 Activity 启动的结果
// 比如没有在 AndroidManifest.xml 中注册的异常就是在这里抛出来的
// 在这个方法内部我们可以看到很多熟悉的异常抛出
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
// 很显然,我们这个地方是跨进程调用,可能抛出RemoteException
throw new RuntimeException("Failure from system", e);
}
return null;
}

这段代码逻辑非常重要:这里是一个IPC的调用,IActivityTaskManager的服务端是ActivityTaskManagerService),所以ActivityTaskManager.getService().startActivity实际上是跨进程调用ActivityManagerService启动Activity之后就会在是ActivityTaskManagerService中去执行Activity 的启动流程。

我们可以稍微看一下以ActivityTaskManager.getService()的方法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}

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

注意:这个地方和Android之前版本的逻辑已经不一致了。之前都是直接ActivityManager.getService()。直接调用到AMS中。这里需要注意。

下面,我们就进入到SystemServer进程中ActivityTaskManagerService的里面看代码的实现,也就是

ActivityTaskManagerService#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
// 代码位于:\frameworks\base\services\core\java\com\android\server\wm\ActivityTaskManagerService.java
/**
* 方法很简单,直接调用的startActivityAsUser
*/
@Override
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());
}
@Override
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /*validateIncomingUser*/);
}

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("startActivityAsUser");
//检查调用者权限
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

// TODO: Switch to user app stacks here.
// 在这里ActivityStartController获取Activity启动控制类。然后通过obtainStarter来获取ActivityStarter类。
// 然后给ActivityStarter设置启动所需的各种参数,最终调用execute()
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();

}

在这里ActivityStartController获取Activity启动控制类ActivityStartController。然后通过ActivityStartController#obtainStarter来获取ActivityStarter类。然后给ActivityStarter设置启动所需的各种参数,最终调用execute()。

1
2
3
4
5
6
7
ActivityStartController getActivityStartController() {
return mActivityStartController;
}

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

这里面说一下我们可以看到ActivityStarter对象是通过其工厂类来获取的。这里用到了工厂模式。

我们有兴趣可以看一下这个工厂方法的实现。

ActivityStarter#execute()

好了,下面,我们来看一下ActivityStarter#execute()的实现。

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
// 代码位于:frameworks\base\services\core\java\com\android\server\wm\ActivityStarter.java
/**
* ActivityStarter是Android 7.0中新加入的类,它是加载Activity的控制类,
* 会收集所有的逻辑来决定如何将Intent和Flags转换为Activity,并将Activity和Task以及Stack相关联。
* Starts an activity based on the request parameters provided earlier.
* 这个方法主要就是mRequest.mayWait来判断是调用startActivityMayWait还是调用startActivity
* @return The starter result.
*/
int execute() {
try {
// TODO(b/64750076): Look into passing request directly to these methods to allow
// for transactional diffs and preprocessing.
if (mRequest.mayWait) {
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
mRequest.intent, mRequest.resolvedType,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
} else {
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
mRequest.outActivity, mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
}
} finally {
onExecutionComplete();
}
}

mRequest.mayWait的赋值是在startActivityAsUser中的setMayWait中,这里传入的true。所以会走startActivityMayWait

那么我们来看一下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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/**
* 这个方法的代码逻辑很多,我们挑重点的看
*/
private int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, int requestRealCallingPid, int requestRealCallingUid,
Intent intent, String resolvedType, IVoiceInteractionSession voiceSession,
IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
int userId, TaskRecord inTask, String reason,
boolean allowPendingRemoteAnimationRegistryLookup,
PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
boolean componentSpecified = intent.getComponent() != null;

final int realCallingPid = requestRealCallingPid != Request.DEFAULT_REAL_CALLING_PID
? requestRealCallingPid
: Binder.getCallingPid();
final int realCallingUid = requestRealCallingUid != Request.DEFAULT_REAL_CALLING_UID
? requestRealCallingUid
: Binder.getCallingUid();

int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = realCallingPid;
callingUid = realCallingUid;
} else {
callingPid = callingUid = -1;
}

// Save a copy in case ephemeral needs it
// 保存Intent临时副本信息,以防临时使用
final Intent ephemeralIntent = new Intent(intent);
// Don't modify the client's object!
intent = new Intent(intent);
if (componentSpecified
&& !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
&& !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
&& !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
&& mService.getPackageManagerInternalLocked()
.isInstantAppInstallerComponent(intent.getComponent())) {
// intercept intents targeted directly to the ephemeral installer the
// ephemeral installer should never be started with a raw Intent; instead
// adjust the intent so it looks like a "normal" instant app launch
intent.setComponent(null /*component*/);
componentSpecified = false;
}

ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
0 /* matchFlags */,
computeResolveFilterUid(
callingUid, realCallingUid, mRequest.filterCallingUid));
if (rInfo == null) {
UserInfo userInfo = mSupervisor.getUserInfo(userId);
if (userInfo != null && userInfo.isManagedProfile()) {
// Special case for managed profiles, if attempting to launch non-cryto aware
// app in a locked managed profile from an unlocked parent allow it to resolve
// as user will be sent via confirm credentials to unlock the profile.
UserManager userManager = UserManager.get(mService.mContext);
boolean profileLockedAndParentUnlockingOrUnlocked = false;
long token = Binder.clearCallingIdentity();
try {
UserInfo parent = userManager.getProfileParent(userId);
profileLockedAndParentUnlockingOrUnlocked = (parent != null)
&& userManager.isUserUnlockingOrUnlocked(parent.id)
&& !userManager.isUserUnlockingOrUnlocked(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
if (profileLockedAndParentUnlockingOrUnlocked) {
rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
computeResolveFilterUid(
callingUid, realCallingUid, mRequest.filterCallingUid));
}
}
}
// Collect information about the target of the Intent.
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

synchronized (mService.mGlobalLock) {
final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
stack.mConfigWillChange = globalConfig != null
&& mService.getGlobalConfiguration().diff(globalConfig) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Starting activity when config will change = " + stack.mConfigWillChange);

final long origId = Binder.clearCallingIdentity();

if (aInfo != null &&
(aInfo.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 &&
mService.mHasHeavyWeightFeature) {
// This may be a heavy-weight process! Check to see if we already
// have another, different heavy-weight process running.
// ·······
}
}

final ActivityRecord[] outRecord = new ActivityRecord[1];
// startActivityMayWait中还是会调用startActivity,调用startActivity
int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
allowBackgroundActivityStart);

// ··········
return res;
}
}

我们看到,这个方法也是调用的startActivity的方法。我们继续向下看。

startActivityMayWait中会调用startActivity,调用startActivity的重载,最后调用postStartActivityProcessing。其中有个重要的调用startActivityUnchecked,我们看下代码

1
2
3
4
// 代码位于:frameworks\base\services\core\java\com\android\server\wm\ActivityStarter.java



文章参考:https://juejin.im/post/5d907722e51d45780b568319

文章参考:https://juejin.im/post/5dda8504e51d452306073434

文章参考:https://www.jianshu.com/p/b78a38c857e8?utm_campaign=haruki&utm_content=note&utm_medium=reader_share&utm_source=weixin