Activity启动流程分析以及如何动态改变启动的页面

Activity启动流程

Posted by Mio4kon on 2017-12-18

分析

首先从ActivitystartActivity()为入口点:

Activity.startActivity

[Activity.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
@Override
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
...
}

Instrumentation.execStartActivity

[Instrumentation.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
33
34
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
//ActivityMonitor用于测试监听Activity是否启动
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
...
int result = ActivityManagerNative.getDefault()
.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;
}
  1. ActivityMonitor是用于检测activity是否已经打开的测试工具类.
  2. ActivityManagerNative.getDefault()获取的是一个ActivityManagerProxy对象,它是ActivityManagerNative的一个内部类.

ActivityManagerNative.gDefault

[ActivityManagerNative.java]

1
2
3
4
5
6
7
8
9
10
11
12
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
IActivityManager am = asInterface(b);
return am;
}
};
static public IActivityManager asInterface(IBinder obj) {
...
return new ActivityManagerProxy(obj);
}

ActivityManagerProxy.startActivity

[ActivityManagerNative::ActivityManagerProxy.java]

1
2
3
4
5
6
7
8
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
...
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
...
return result;
}

以上代码都是运行执行进程中的.通过Binder通知消息START_ACTIVITY_TRANSACTION到远端进程,也就是ActivityManagerNative中的代码.

ActivityManagerNative.onTransact

[ActivityManagerNative.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
...
int result = startActivity(app, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
...
return true;
}
...
}

ActivityManagerNative是一个抽象类.真正实现类是ActivityManagerService,也就是大家常说的AMS.

以上流程如下图:


上图binder通知的左边为调用方所在的进程.

ActivityManagerService.startActivity

[ActivityManagerService.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, ALLOW_FULL_ONLY, "startActivity", null);
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, false, userId, null, null);
}

ActivityStackSupervisor.startActivityMayWait

[ActivityStackSupervisor.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
33
34
35
36
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 config,
Bundle options, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
//通过参数构造ActivityInfo
ActivityInfo aInfo =
resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
ActivityContainer container = (ActivityContainer)iContainer;
synchronized (mService) {
...
if (aInfo != null &&
(aInfo.applicationInfo.privateFlags
&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
//heavy-weight process 选择哪个程序打开Activity
}
}
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
componentSpecified, null, container, inTask);
....
return res;
}
}
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
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage,
int realCallingPid, int realCallingUid, int startFlags, Bundle options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
ActivityContainer container, TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
//获取调用者的uid和pid
...
//调用者Activity记录对象
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
//resultTo 调用者的Activity的Token
sourceRecord = isInAnyStackLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Will send result to " + resultTo + " " + sourceRecord);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
final int launchFlags = intent.getFlags();
//对一些参数进行校验,校验失败后将错误码赋值给err
...
final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
//如果检查参数有异常直接返回
//调用者页面需要返回结果时,回复RESULT_CANCELED
if (err != ActivityManager.START_SUCCESS) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1,
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
return err;
}
boolean abort = false;
//检查调用者是否有权限打开Activity
final int startAnyPerm = mService.checkPermission(
START_ANY_ACTIVITY, callingPid, callingUid);
...
if (abort) {
//没有权限的时候,直接返回
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
ActivityOptions.abort(options);
return ActivityManager.START_SUCCESS;
}
//创建activity记录对象
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, this, container, options);
if (outActivity != null) {
outActivity[0] = r;
}
...
//mFocusedStack: 正在接收或者将要启动的Activity堆栈
final ActivityStack stack = mFocusedStack;
if (voiceSession == null && (stack.mResumedActivity == null
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
//不允许后台打开app的话将Activity放入PendingActivityLaunch
PendingActivityLaunch pal =
new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
mPendingActivityLaunches.add(pal);
ActivityOptions.abort(options);
return ActivityManager.START_SWITCHES_CANCELED;
}
}
//处理被禁止切换而导致等待的Activity
doPendingActivityLaunchesLocked(false);
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
...
return err;
}

ActivityStackSupervisor.startActivityUncheckedLocked

1
2
3
4
5
6
7
8
9
10
final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, Bundle options, TaskRecord inTask) {
//逻辑很多,主要是根据传入的参数来配置task
...
ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
targetStack.mLastPausedActivity = null;
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
return ActivityManager.START_SUCCESS;
}

startActivityUncheckedLocked中的逻辑非常多,主要是根据传入的intent等参数来设置Launch Mode.然后调用startActivityLocked方法.

ActivityStack.startActivityLocked

[ActivityStack.java]

1
2
3
4
5
6
7
8
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
//根据lunchMode处理task
...
if (doResume) {
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}
}

ActivityStackSupervisor.resumeTopActivitiesLocked

[ActivityStackSupervisor.java]

1
2
3
4
5
6
7
8
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
return result;
}

ActivityStack.resumeTopActivityLocked

[ActivityStack.java]

1
2
3
4
5
6
7
8
9
10
11
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
...
boolean result = false;
try {
...
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}

ActivityStack.resumeTopActivityInnerLocked

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
if (DEBUG_LOCKSCREEN) mService.logLockScreen("");
if (!mService.mBooting && !mService.mBooted) {
// 系统还没启动好
return false;
}
ActivityRecord parent = mActivityContainer.mParentActivity;
// 获取栈顶的Activity(将要启动的)
final ActivityRecord next = topRunningActivityLocked(null);
...
final TaskRecord prevTask = prev != null ? prev.task : null;
//如果将要启动的Activity为空时
if (next == null) {
// There are no more activities!
final String reason = "noMoreActivities";
if (!mFullscreen) {
//到栈下面一个activity
final ActivityStack stack = getNextVisibleStackLocked();
if (adjustFocusToNextVisibleStackLocked(stack, reason)) {
return mStackSupervisor.resumeTopActivitiesLocked(stack, prev, null);
}
}
// 回到Lancher
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
}
next.delayedResume = false;
...
// pause 当前activity, resume 将要启动的activity
boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}
if (pausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
// happens to be sitting towards the end.
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
...
if (prev != null && prev != next) {
if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev)
&& next != null && !next.nowVisible) {
mStackSupervisor.mWaitingVisibleActivities.add(prev);
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Resuming top, waiting visible to hide: " + prev);
} else {
//将要显示的activity已经显示了. 隐藏之前activity的window
if (prev.finishing) {
mWindowManager.setAppVisibility(prev.appToken, false);
..
} else {
..
}
}
}
// Launching this app's activity, make sure the app is no longer
// considered stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
next.packageName, false, next.userId); /* TODO: Verify if correct userid */
} catch (RemoteException e1) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ next.packageName + ": " + e);
}
//即将打开next页面.告诉WM之前的页面准备隐藏了.
boolean anim = true;
if (prev != null) {
...
mWindowManager.prepareAppTransition(prev.task == next.task
? AppTransition.TRANSIT_ACTIVITY_CLOSE
: AppTransition.TRANSIT_TASK_CLOSE, false);
mWindowManager.setAppWillBeHidden(prev.appToken);
mWindowManager.setAppVisibility(prev.appToken, false);
...
} else {
...
}
//开始resume
ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next);
// This activity is now becoming visible.
mWindowManager.setAppVisibility(next.appToken, true);
// 开始打印启动日志
next.startLaunchTickingLocked();
ActivityRecord lastResumedActivity =
lastStack == null ? null :lastStack.mResumedActivity;
ActivityState lastState = next.state;
mService.updateCpuStats();
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)");
next.state = ActivityState.RESUMED;
mResumedActivity = next;
next.task.touchActiveTime();
mRecentTasks.addLocked(next.task);
mService.updateLruProcessLocked(next.app, true, null);
updateLRUListLocked(next);
mService.updateOomAdjLocked();
//判断屏幕旋转是否需要update
boolean notUpdated = true;
if (mStackSupervisor.isFrontStack(this)) {
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
if (config != null) {
next.frozenBeforeDestroy = true;
}
notUpdated = !mService.updateConfigurationLocked(config, next, false, false);
}
...
try {
...
//app thread resume 页面
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
..
} catch (Exception e) {
// 如果失败,重新start页面
...
mStackSupervisor.startSpecificActivityLocked(next, true, false);
return true;
}
//重新resume
...
return true;
}

该方法主要做了:

  1. pause当前页面,resume即将启动的页面.
  2. 如果当前页面为空,启动pause launch页面.
  3. resume,并开启打印日志等.
  4. resume失败,调用startSpecificActivityLocked重新打开页面.

我们分析第一次启动流程.这里会走startSpecificActivityLocked的方法.

ActivityStackSupervisor.startSpecificActivityLocked

[ActivityStackSupervisor.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
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// 是否app的进程已经开启.
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
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);
}
//app进程已经打开的分支
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.
}
//app进程没有打开的分支
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}

该方法主要做了:

  1. 判断app进程是否开启,如果开启了则直接调用realStartActivityLocked方法.
  2. 否则调用startProcessLocked方法.

这里我们假定进程已经开启好了.直接分析realStartActivityLocked方法.

ActivityStackSupervisor.realStartActivityLocked

[ActivityStackSupervisor.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
33
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
//开启启动打印日志,更新进程优先级等.
...
final ActivityStack stack = task.stack;
try {
...
//如果需要dex优化则进行dex优化.
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
r.sleeping = false;
r.forceNewConfig = false;
mService.showAskCompatModeDialogLocked(r);
r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
...
//设置前台进程为当前activity的进程
app.forceProcessStateUpTo(mService.mTopProcessState);
//app thread 启动activity
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
...
} catch (RemoteException e) {
...
}
return true;
}

该方法主要做了:

  1. 启动打印日志,更新进程优先级等.
  2. 如果启动的activity所属的Package需要dex优化,则优化.
  3. 设置启动activity的进程为app的前台进程.
  4. 最后调用ApplicationThreadscheduleLaunchActivity方法启动页面.

ApplicationThreadProxy.scheduleLaunchActivity

[ApplicationThreadNative::ApplicationThreadProxy.java]

1
2
3
4
5
6
7
8
9
10
11
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) throws RemoteException {
...
mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
..
}

ApplicationThreadNative.onTransact

[ApplicationThreadNative.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION:
{
scheduleLaunchActivity(intent, b, ident, info, curConfig, overrideConfig, compatInfo,
referrer, voiceInteractor, procState, state, persistentState, ri, pi,
notResumed, isForward, profilerInfo);
return true;
}
return super.onTransact(code, data, reply, flags);
}

和之前一样.通过Binder通知ApplicationThreadNative去执行.最终实现是它的子类ApplicationThread,它是ActivityThread的一个内部类.

到此为止AMS的工作基本完成了.接下来就是通知客户端也就是ApplicationThread去完成启动.
我们先看下之前的AMS的流程.

ApplicationThread.scheduleLaunchActivity

从现在开始已经回到了App进程中了:

[ActivityThread::ApplicationThread.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
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);
ActivityClientRecord r = new ActivityClientRecord();
updatePendingConfiguration(curConfig);
...
sendMessage(H.LAUNCH_ACTIVITY, r);
}

这里通过发送一个message来通知AT处理 , 这里H其实是一个Handler.

ActivityThread.handleMessage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void handleMessage(Message msg) {
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);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}

ActivityThread.handleLaunchActivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
..
Activity a = performLaunchActivity(r, customIntent);
...
} else {
// If there was an error, for any reason, tell the activity
// manager to stop us.
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
// Ignore
}
}
}

ActivityThread.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
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
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//获取packageInfo,component等.
...
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.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);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
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);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
//调用onCreate生命周期.
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
//调用onStart生命周期.
activity.performStart();
r.stopped = false;
}
//调用OnRestoreInstanceState生命周期.
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
//调用onPostCreate生命周期.
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}

该方法主要做了:

  1. 生成Activity对象.
  2. 通过Instrumentation调用Activity的启动的生命周期.

这里我们看下callActivityOnCreate方法.

Instrumentation.callActivityOnCreate

[Instrumentation.java]

1
2
3
4
5
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}

Activity.performCreate

[Activity.java]

1
2
3
4
5
6
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}

至此Activity的启动流程就分析完成了. 最后这部分的流程图如下:

总结:

由于启动流程比较复杂,尤其是AMS中的代码.本篇主要列出了一些重点流程以及其中的一些方法.简单来说就是客户端(这里可以是Launcher可以是自己的APP)通过Binder通知AMS.AMS处理完成后,通知客户端生成Activity类并调用其生命周期.

问题:

假如有一个需求,我们在代码写入启动ActivityA ,但我们在AndroidManifest中注册的却是ActivityB,我们希望最终打开的是ActivityA.如何Hook呢?

这个需求其实正是有些插件框架所使用的.在主工程中的AndroidManifest插入备用桩.然后最终会打开插件中的Activity.

其实分析完启动流程后,我们就应该知道AMS中做了很多校验,包括处理了Activity栈.但一个新启动的Activity真正被启动其实与AMS并没有太大关系.我们只需要在binder通知AMS之前把Component替换为AndroidManifest中注册的Activity,然后在AMS校验完成之后再将替换的还原为真正要启动的页面即可.

  1. 动态代理 hook ActivityManagerProxy.将参数中的intent替换为AndroidManifest中的备用桩.
  2. 通过反射拿到H类,并复写其的Handler Callback,将intent替换回想要打开的Activity即可.

当然最终实现下来可能还会有异常.根据抛的异常栈.我们再进行hook.

例如,这里可能会抛:NameNotFoundException异常.如下:

可以发现其实已经调用了PluginActivityonCreate生命周期.onCreate中系统又做了一次校验.

1
2
3
4
5
6
7
8
9
@Nullable
public static String getParentActivityName(Context context, ComponentName componentName)
throws NameNotFoundException {
PackageManager pm = context.getPackageManager();
//抛错
ActivityInfo info = pm.getActivityInfo(componentName, PackageManager.GET_META_DATA);
...
return parentActivity;
}

我们发现getActivityInfoIPackageManager接口中的方法.那么我们可以通过反射在ActivityThread中拿到pm对象,再通过动态代理来替换掉ComponentName即可.