前言
本文的启动流程是同一个app内的Activity启动流程,所以没有涉及到新建进程的过程,后面再进行补充。另外源码非常庞大,函数参数经常10个以上,所以会用省略号代替。另外为了函数流程更加直观我使用Class.Method(……)来表示。
环境准备
1.源代码一份,我使用的Android 7.1.2。重点是可以有真机或者模拟器调试
2.使用Android studio将源码导入,导入方法百度上很多。下次写篇导入的文章,主要有些注意事项,比如android.R的导入。
3.找到自己的想要调试的方法,设置好断点,开始调试即可。
4.调试过程中可能涉及到handler,多线程之前的关系,自己要区分好。
第一阶段
先上张流程图:
第一阶段是AMS先pause正在显示的Activity
//初始化package&activity信息
ActivityStarter.startActivityMayWait(......)
//权限判断,voiceSession判断,等等
ActivityStarter.startActivityLocked(......)
//初始化Starter,计算launcher flag,
//其实就是找到可用的ActivityStack,可用/新建TaskRecord,
ActivityStarter.startActivityUnchecked(......)
//把将要启动的Activity“压入task栈顶”,调整task到“栈顶”
ActivityStack.startActivityLocked(......)
//修改mFocusedActivity
ActivityManagerService.setFocusedActivityLocked
//把将要启动Activiy所在的ActivityStack移动到“栈顶”
ActivityStackSupervisor.moveActivityStackToFront
//开始Resume Activity
ActivityStack.resumeTopActivityInnerLocked(......)
//找到当前focused的ActivityStack
ActivityStackSupervisor.pauseBackStacks(......)
//这里的this(ActivityStack)是将要pause的activity所在的ActivityStack,
ActivityStack.startPausingLocked(......, false/* dontWait*/){
......
ActivityRecord prev = mResumedActivity;
......
mResumedActivity = null;
//把stack中的,mPausingActivity 赋值为 mResumedActivity
mPausingActivity = prev;
mLastPausedActivity = prev;
mLastNoHistoryActivity = ......;
//修改mPausingActivity状态为PAUSING
prev.state = ActivityState.PAUSING;
.......
if (prev.app != null && prev.app.thread != null) {
......
//这里向其实是向app请求prev activity pause。此时app端是binder服务端
//app调完onPause后又会向ActivityMangerService回调activityPause
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
......
}
......
if (dontWait /* false */ ) {
// If the caller said they don't want to wait for the pause, then complete
// the pause now.
completePauseLocked(false, resuming);
return false;
} else {
// Schedule a pause timeout in case the app doesn't respond.
// We don't give it much time because this directly impacts the
// responsiveness seen by the user.
// 走这里,可以提早返回,而不用等prev pause ok
// 这样发起startActivity的app不会阻塞
Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
msg.obj = prev;
prev.pauseTime = SystemClock.uptimeMillis();
mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT /* 500ms */);
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
return true;
}
}
好了, 第一阶段的代码解析到这,你们猜猜现在现在线程运行状态是怎样的?
1. 调用startActivity的app client使用的binder线程, 拿到拿到了AMS的句柄
2.ActivityManager线程是在等锁释放的,所以这个PAUSE_TIMEOUT_MSG的消息还处理不了
到这里大家是否有疑问:
1.AMS已经调用了schedulePauseActivity
2.但是从Thread maps上看,被pause的app进程没有通过binder向AMS回调通知activity pause的状态
因为目标app的startActivity流程还没执行完。AMS只是向binder驱动请求了这个过程,目标app的binder主线程还在执行startActivity,自然没办法处理AMS来的其他消息,注意这里app是Server。继续调试让startActivity的binder过程完成。那么问题又来了
1.PAUSE_TIMEOUT_MSG先执行
2.目标app的先把pause的状态binder到AMS
正常是2先执行
但是调试的时候,是1先来到,如下图:
竟然是先PAUSE_TIMEOUT_MSG,但是当你了解handler的delay机制就知道为啥了
机制:度娘正常的结果我是调试出来的,如下调试方法:
首先在message处理的地方加上断点打印
在binder回调的地方加上
结果如下:
第二阶段
从目标app把pause的状态binder到AMS的过程开始
ActivityManagerService.activityPaused(IBinder token){
final long origId = Binder.clearCallingIdentity();
synchronized(this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
//这里是通过token拿到的ActivityStack
stack.activityPausedLocked(token, false);
}
}
Binder.restoreCallingIdentity(origId);
}
ActivityStack.activityPausedLocked(IBinder token, boolean timeout){
final ActivityRecord r = isInStackLocked(token);
if (r != null) {
//去掉PAUSE_TIMEOUT_MSG消息
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
if (mPausingActivity == r) {
......
completePauseLocked(true, null);
return;
} else {
......
}
......
}
ActivityStack.completePauseLocked(Boolean resumeNext /* true */,......){
//第一阶段的将要pause的activity
ActivityRecord prev = mPausingActivity;
if (prev != null) {
final boolean wasStopping = prev.state == ActivityState.STOPPING;
prev.state = ActivityState.PAUSED;
if (prev.finishing /* 这里为false */) {
//进入fainish流程
prev = finishCurrentActivityLocked(......);
} else if (prev.app != null) {
......
}
}
if (resumeNext) {
//获取顶层stack
final ActivityStack topStack = mStackSupervisor.getFocusedStack();
if (!mService.isSleepingOrShuttingDownLocked() /* true */) {
mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
}else{
......
}
}
......
}
ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(......) {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(......);
}
......
return false;
}
ActivityStack.resumeTopActivityUncheckedLocked(......){
......
result = resumeTopActivityInnerLocked(prev, options);
......
}
//又来到这个方法了,不过这次不会走pause流程
ActivityStack.resumeTopActivityInnerLocked(......){
......
boolean pausing = mStackSupervisor.pauseBackStacks(......);
//第一阶段置null了
if (mResumedActivity/*null*/ != null) {
pausing |= startPausingLocked(......);
}
if (pausing /* false */) {
......
}else if(mResumedActivity/*null*/ == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()){
......
}
//一系列令人窒息的操作
......
//这两个都为null
if (next.app != null && next.app.thread != null) {
//一顿操作
......
}else{
......
//重点
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
}
ActivityStackSupervisor.startSpecificActivityLocked(......){
// Is this activity's application already running?
// 如果是启动一个未启动的app,那么这里为null
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) {
......
realStartActivityLocked(r, app, andResume, checkConfig);
return;
}
}
ActivityStackSupervisor.realStartActivityLocked(......){
//保证所有的activity没有resumed的
if (!allPausedActivitiesComplete()) {
// While there are activities pausing we skipping starting any new activities until
// pauses are complete. NOTE: that we also do this for activities that are starting in
// the paused state because they will first be resumed then paused on the client side.
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
"realStartActivityLocked: Skipping start of r=" + r
+ " some activities pausing...");
return false;
}
//超级窒息的操作
......
//重点来了,还记得之前的说的嘛,这个pause的binder还没结束,所以这个操作在app端不会立即执行
//但是有个前提:启动的不是另外一个app进程的activity
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
......
if (andResume) {
// As part of the process of launching, ActivityThread also performs
// a resume.
stack.minimalResumeActivityLocked(r);
}
......
}
//到这里马上进入下一个阶段了
ActivityStack.minimalResumeActivityLocked(ActivityRecord r) {
//修改activity的状态
r.state = ActivityState.RESUMED;
mResumedActivity = r;
r.task.touchActiveTime();
mRecentTasks.addLocked(r.task);
//这里和pause差不多,也会发一个IDLE_TIMEOUT_MSG超时广播
completeResumeLocked(r);
mStackSupervisor.checkReadyForSleepLocked();
setLaunchTime(r);
}
第三阶段
第三阶段比较简单,AMS等待启动的Activity 通过binder回调activityIdle,而这个过程是通过IdleHandler来实现
//Activity端的实现,
ActivityThread.handleResumeActivity(......){
......
if (!r.onlyLocalRequest) {
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(
TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}
r.onlyLocalRequest = false;
......
}
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
......
IActivityManager am = ActivityManagerNative.getDefault();
......
am.activityIdle(a.token, a.createdConfig, stopProfiling);
......
return false;
}
}
//来到AMS
ActivityManagerService.activityIdle(......){
......
mStackSupervisor.activityIdleInternalLocked(token, false, config);
......
}
//这里不详细分析了
activityIdleInternalLocked(.......){
......
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
......
}
总结一下:
1. 启动一个Activity的流程往往涉及到至少一个app和AMS的交互
2. 每个Activity都有一个“token”来标识自己
3. 启动哪个Activity由ActivityStarter控制
4. 所有的ActivityStack由ActivityStackSupervisor管理
5. 一个ActivityStack由多个TaskRecord组成
6. 一个TaskRecord由多个ActivityRecord组成
7. Android N上一共有5种Stask,各有各的用途
8. Android中对Activity的管理其实并不是真正意义上的stack
9. Binder真的很重要,Android的灵魂,建议先熟悉了Binder机制再看代码
10. AMS源码调用关系复杂,但是每个函数基本都干自己的事情,每个函数最重要的通信桥梁不是函数参数,而是一些很重要全局变量。很多函数会因为某个全局变量的值不一样会有不一样的结果。
11. Android系统对耗电量真的放的很宽,正常来说函数调用越多,耗电越多。