上一篇文章我们讲到了寻找复用的任务栈,那么到目前为止不论存不存在复用的任务栈,我们接下去的处理其实都是统一的,现在我们就继续按照源码走下去。
```java
// 待启动的Activity包名空,返回
if (mStartActivity.packageName == null) {
final ActivityStack sourceStack = mStartActivity.resultTo != null
? mStartActivity.resultTo.getStack() : null;
if (sourceStack != null) {
sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
null /* data */);
}
ActivityOptions.abort(mOptions);
return START_CLASS_NOT_FOUND;
}
```
这个方法做了下校验,如果启动的Activity的包名是空的,那么会返回报错。同时如果他需要向调用者发送回复会调用sendActivityResultLocked方法,我们稍稍看下这个方法:
```java
// 回复给forResult的Activity消息
void sendActivityResultLocked(int callingUid, ActivityRecord r,
String resultWho, int requestCode, int resultCode, Intent data) {
if (callingUid > 0) {
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
data, r.getUriPermissionsLocked(), r.userId);
}
if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
+ " : who=" + resultWho + " req=" + requestCode
+ " res=" + resultCode + " data=" + data);
if (mResumedActivity == r && r.app != null && r.app.thread != null) {
try {
ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
// 回复给result的数据
list.add(new ResultInfo(resultWho, requestCode,
resultCode, data));
// 开始binder给目标result的activity回复消息
// 这里是AMS中,通过ApplicationProxy的transact方法,然后
// 调到服务端IApplicationThread.Stub的scheduleSendResult方法
// 由于ApplicationThread extends IApplicationThread.Stub继承了
//并且覆写了scheduleSendResult方法,最后最终走到ApplicationThread的
// scheduleSendResult方法,在通过H一直调到onActivityResult
r.app.thread.scheduleSendResult(r.appToken, list);
return;
} catch (Exception e) {
Slog.w(TAG, "Exception thrown sending result to " + r, e);
}
}
r.addResultLocked(null, resultWho, requestCode, resultCode, data);
}
```
这个方法我们看到,主要通过scheduleSendResult给调用者回复,scheduleSendResult这个方法通过binder调用到app进场,这个我们后面说到切换进程的地方再说,这里我们了解这里的逻辑就可以。
#启动有复用任务栈的Activity
我们接着看后面的代码:
```java
// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
// 取出当前焦点tack,以及获取他顶部的Activity
final ActivityStack topStack = mSupervisor.mFocusedStack;
final ActivityRecord topFocused = topStack.topActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null // 顶部这个Activity非空
&& top.realActivity.equals(mStartActivity.realActivity) // 顶部这个Activity的component和要启动的一样
&& top.userId == mStartActivity.userId // userid一样
&& top.app != null && top.app.thread != null // ProcessRecord非空,ApplicationProxy非空
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask); // single_top或者single_task
// 执行这里的话,说明顶部的这个Activity可以复用,不用启用一个新的
// 会执行onNewIntent
if (dontStart) {
ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
// 执行onNewIntent
top.deliverNewIntentLocked(
mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
}
```
这个方法中可以看到dontStart这个变量,这个变量有一堆的判断,总的来说,就是如果要启动的Activity是single_top或者single_task启动模式的,并且栈顶Activity和启动的Activity是一样的,那么会调用后面的resumeFocusedStackTopActivityLocked和deliverNewIntentLocked方法,这两个方法前面都看到过,一个是onresume,一个是onNewIntent的调用。到这里这种情况的Activity启动就处理完了,后面继续看其他情况的启动。
# 其余的启动情况
```java
// Should this be considered a new task?
int result = START_SUCCESS;
// 没有回复
// 没有指定任务栈
// mAddingToTask到这里如果还是false的话,就说明没有找到task了
// new_task
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
// 没有复用task就创建task
// 把activity加入到task中
// 设置ActivityStack为焦点
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) { // 调用者非空
// 任务栈会用调用者的,然后处理任务栈和activityStack的关系
// 以及处理activity插入任务栈等
result = setTaskFromSourceRecord();
} else if (mInTask != null) { // 指定任务栈
result = setTaskFromInTask();
} else {
// This not being started from an existing activity, and not part of a new task...
// just put it in the top task, though these days this case should never happen.
// 这里就是先获取合适的ActivityStack,然后获取他最上面activty对应的task,然后把目标activity加入到这个task中
setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) { // 非START_SUCCESS就返回
return result;
}
```
这段代码最开始,可以看到google的注释,Should this be considered a new task?其实并不是说这里开始都是要创建新的任务栈,而且前面的处理都是针对有复用任务栈的情况,现在开始有没有复用栈都有可能,我们接着看代码。
# 新任务栈
下面有几个分支,我们首先看第一个,要进入第一个分支,这个需要同时满足四个条件
1. 没有需要回复的调用者
2. 没有指定的taskRecord
3. mAddingToTask为false
4. 有FLAG_ACTIVITY_NEW_TASK标志
为什么说有这四项就可以确定是一个新任务栈呢?(其实还有个条件就是mReuseTask,这个在下面调用的方法中就可以看到)。首先第一项没有需要回复的调用者,前面有说过如果调用者和被调用者在不同的任务栈中,处理起来会很复杂,所以前面有代码已经分析过,对于这种情况,google会给调用者发送一个消息后,然后把调用者给置了,所以执行到这里不会有这种情况。
第二项是调用时候指定的任务栈,如果为空那肯定就说明当前没有一个具体的任务栈给出了。
第三项mAddingToTask这个变量在前面的分析中看到,如果确定了一个要加入的taskRecord,就会把这个值置为true,否则就是false。
第四项只有新的任务栈才会有这个标志,这个是个必要条件
所以以上四项同时都满足的话,那肯定是个新任务栈了,下面我们看下调用的方法setTaskFromReuseOrCreateNewTask:
```java
private int setTaskFromReuseOrCreateNewTask(
TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
// 获取一个要加入的ActivityStack
mTargetStack = computeStackFocus(
mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
// Do no move the target stack to front yet, as we might bail if
// isLockTaskModeViolation fails below.
if (mReuseTask == null) { // 如果没有复用的TaskRecord进这里
// 创建一个TaskRecord
final TaskRecord task = mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
// 把Activity加入到对应的taskRecord中
addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
if (mLaunchBounds != null) {
final int stackId = mTargetStack.mStackId;
if (StackId.resizeStackWithLaunchBounds(stackId)) {
mService.resizeStack(
stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
} else {
mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
}
}
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in new task " + mStartActivity.getTask());
} else {
// 有复用task的话就直接加入好了
addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
}
if (taskToAffiliate != null) {
mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
}
if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (!mMovedOtherTask) {
// If stack id is specified in activity options, usually it means that activity is
// launched not from currently focused stack (e.g. from SysUI or from shell) - in
// that case we check the target stack.
updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
}
if (mDoResume) {
// 把当前ActivityStack放到同一屏幕下的最顶端
// 设置为焦点ActivityStack
mTargetStack.moveToFront("reuseOrNewTask");
}
return START_SUCCESS;
}
```
这个方法首先调用computeStackFocus方法,这个方法之前我们看到过,来计算合适的启动ActivityStack。之后根据mReuseTask这个变量是否为空来判断有没有复用的taskRecord,如果为空就需要创建taskRecord,然后把Activity加入,否则就直接加入taskRecord。我们先看下创建taskRecord方法:
```java
// 创建一个TaskRecord,同时会加入到ActivityStack顶部
TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
boolean toTop, int type) {
// 创建一个TaskRecord
TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
voiceInteractor, type);
// add the task to stack first, mTaskPositioner might need the stack association
// 把taskRecord插入ActivityStack的task集合中
addTask(task, toTop, "createTaskRecord");
final boolean isLockscreenShown =
mService.mStackSupervisor.mKeyguardController.isKeyguardShowing();
if (!layoutTaskInStack(task, info.windowLayout) && mBounds != null && task.isResizeable()
&& !isLockscreenShown) {
task.updateOverrideConfiguration(mBounds);
}
task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
return task;
}
```
这个方法比较简单new一个TaskRecord,可以看到我们之前在寻找复用栈时候有说过,会比较每个taskRecord的intent,他第一次赋值的时候就是在创建taskRecord的时候,这个的intent就是启动的Activity的intent,然后把这个taskRecord加入前面得到的ActivityStack,最后是处理和WMS相关的我们暂时不去关注他。回到前面的方法,会调用addOrReparentStartingActivity方法把要启动的Activity加入刚创建的taskRecord。
```java
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
// 如果要启动的这个Activity没有任务栈,或者和现在这个要加入的任务栈是一样的,就把他加入
if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
parent.addActivityToTop(mStartActivity);
} else {
// 如果启动的task和要加入的不一样,需要把activity从老的task中取出,放入新的task中
mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
}
}
```
这里可以看到,如果要启动的Activity没有taskRecord,或者原本他的TaskRecord就是参数传入的这个,那就直接把Activity加入这个taskRecord。否则说明这个Activity原本的taskRecord和要要加入的不一样,那就调用reparent方法。之前的文章我们看到过把一个taskRecord从一个ActivityStack中移动到另一个ActivityStack中,现在这里是把一个Activity从一个taskRecord移动到另一个,我们看下方法实现:
```java
void reparent(TaskRecord newTask, int position, String reason) {
final TaskRecord prevTask = task; // 该Activity之前所在的task
if (prevTask == newTask) { // 和要加入的不能一样,一样也不要移动了
throw new IllegalArgumentException(reason + ": task=" + newTask
+ " is already the parent of r=" + this);
}
// TODO: Ensure that we do not directly reparent activities across stacks, as that may leave
// the stacks in strange states. For now, we should use Task.reparent() to ensure that
// the stack is left in an OK state.
if (prevTask != null && newTask != null && prevTask.getStack() != newTask.getStack()) {
throw new IllegalArgumentException(reason + ": task=" + newTask
+ " is in a different stack (" + newTask.getStackId() + ") than the parent of"
+ " r=" + this + " (" + prevTask.getStackId() + ")");
}
// Must reparent first in window manager
mWindowContainerController.reparent(newTask.getWindowContainerController(), position);
// Remove the activity from the old task and add it to the new task.
// 从老的task中移除
prevTask.removeActivity(this, true /*reparenting*/);
// 加入到新的task中
newTask.addActivityAtIndex(position, this);
}
```
这里方法不长,最重要的就是最后两句。一个是从老的task中移除,一个是加入新的task。我们先看从老的task中移除:
```java
boolean removeActivity(ActivityRecord r, boolean reparenting) {
if (r.getTask() != this) {
throw new IllegalArgumentException(
"Activity=" + r + " does not belong to task=" + this);
}
r.setTask(null /*task*/, reparenting); // 把activity的task置空
if (mActivities.remove(r) && r.fullscreen) { // 从task的Activity集合中移除本activity
// Was previously in list.
numFullscreen--; // 如果是全屏的话,数量-1
}
if (r.isPersistable()) {
mService.notifyTaskPersisterLocked(this, false);
}
if (getStackId() == PINNED_STACK_ID) {
// We normally notify listeners of task stack changes on pause, however pinned stack
// activities are normally in the paused state so no notification will be sent there
// before the activity is removed. We send it here so instead.
mService.mTaskChangeNotificationController.notifyTaskStackChanged();
}
if (mActivities.isEmpty()) {
return !mReuseTask;
}
updateEffectiveIntent();
return false;
}
```
这个方法主要的处理是把这个Activity所属的task置空,然后从这个task的activity集合中移除这个activity,其余的代码是一些额外的逻辑,这里不详细展开。我们下面在看下加入新的task中的代码:
```java
void addActivityAtIndex(int index, ActivityRecord r) {
TaskRecord task = r.getTask();
if (task != null && task != this) {
throw new IllegalArgumentException("Can not add r=" + " to task=" + this
+ " current parent=" + task);
}
r.setTask(this);
// Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
if (!mActivities.remove(r) && r.fullscreen) { // 如果集合中已经有了,移除
// Was not previously in list.
numFullscreen++; // 是一个全屏显示的Activity,数量++
}
// Only set this based on the first activity
if (mActivities.isEmpty()) { // 新的任务栈
taskType = r.mActivityType; // 设置任务栈的类型
isPersistable = r.isPersistable();
mCallingUid = r.launchedFromUid; // 调用者uid
mCallingPackage = r.launchedFromPackage; // 调用者报名
// Clamp to [1, max].
maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
ActivityManager.getMaxAppRecentsLimitStatic());
} else {
// Otherwise make all added activities match this one.
r.mActivityType = taskType;
}
final int size = mActivities.size();
if (index == size && size > 0) {
final ActivityRecord top = mActivities.get(size - 1);
if (top.mTaskOverlay) { // 如果顶部Activity是要在最上面的,那么把加入的位置减一
// Place below the task overlay activity since the overlay activity should always
// be on top.
index--;
}
}
index = Math.min(size, index);
mActivities.add(index, r); // 加入Activity集合
updateEffectiveIntent();
if (r.isPersistable()) {
mService.notifyTaskPersisterLocked(this, false);
}
// WMS 的一些处理
// Sync. with window manager
updateOverrideConfigurationFromLaunchBounds();
final AppWindowContainerController appController = r.getWindowContainerController();
if (appController != null) {
// Only attempt to move in WM if the child has a controller. It is possible we haven't
// created controller for the activity we are starting yet.
mWindowContainerController.positionChildAt(appController, index);
}
r.onOverrideConfigurationSent();
// Make sure the list of display UID whitelists is updated
// now that this record is in a new task.
mService.mStackSupervisor.updateUIDsPresentOnDisplay();
}
```
方法的开始做下校验,然后把这个activity的task设置为加入的这个task,之后为了防止重复加入,先尝试从这个task的activity集合中移除这个activity,确保没有相同的存在。之后就开始加入这个Activity集合了,当然如果当前Activity集合是空的话,说明还要把调用者的一些信息设置给这个task,比如uid,包名之类的,可以让task知道他的调用者是谁。之后,除了那些必须要在顶部显示的Activity外,把启动的Activity插入这个集合中。这样的话,要启动的Activity就从一个老的task中被移动到新的task中了。
我们回到setTaskFromReuseOrCreateNewTask方法,上面说的是没有可以复用的taskRecord的时候先创建taskRecord,然后把Activty移动到这个taskRecord中,如果有可用的taskRecord的时候直接移动到他之中就可以了,方法也是addOrReparentStartingActivity,就不多说了。
最后需要把这个ActivityStack移动到最前面,调用的是moveToFront,这个方法上一篇文章有过分析,这么就不重复讲了。
# 来自调用者的任务栈
上面这个是新建一个任务栈的方法,我们接着看第二个分支mSourceRecord非空的时候,这个时候就说明任务栈是来自于调用者的,当然我们其实在前面setTaskFromIntentActivity方法中有看到,其实mSourceRecord有几种情况下是被赋值于寻找到的复用栈的,具体可以往前面看下,这里为了叙述方便,我们就统一认为是调用者了。当有调用者的时候,我们从调用者中获取任务栈,调用的方法是setTaskFromSourceRecord,我们先看这个方法的前半部分:
```java
private int setTaskFromSourceRecord() {
if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
// 获取调用方Activity的TaskRecord,这个方法由于调用者不为空,又因为进入这个
// 方法后,会用这个调用的task,所以sourceTask是目标的task
final TaskRecord sourceTask = mSourceRecord.getTask();
// 获取调用方的ActivityStack
final ActivityStack sourceStack = mSourceRecord.getStack();
// We only want to allow changing stack if the target task is not the top one,
// otherwise we would move the launching task to the other side, rather than show
// two side by side.
// 如果调用者Activity的task不是他所在ActivityStack的最上面一个
final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
if (moveStackAllowed) { // 那么就计算获取要启动的ActivityStack
mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
mOptions);
}
if (mTargetStack == null) { // 如果没有可以复用的ActivityStack
mTargetStack = sourceStack; // 就用调用者的ActivityStack
} else if (mTargetStack != sourceStack) { // 如果计算出的启动ActivityStack和调用者的不一样
// 把调用者的task加入到启动的ActivityStack中,当然里面也会把task从老的移除
sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
!ANIMATE, DEFER_RESUME, "launchToSide");
}
// 注意经过上面if else的处理,任务栈sourceTask和ActivityStack已经确定了,下面就只要
// 处理把这个task移动到顶部就可以了
final TaskRecord topTask = mTargetStack.topTask(); // 获取目标ActivityStack顶部task
// 目标ActivityStack顶部的task和调用者的task不是一个,
if (topTask != sourceTask && !mAvoidMoveToFront) {
// 进入这里说明目标ActivityStack顶部不是目标的任务栈sourceTask
// 所以下面方法把目标任务栈sourceTask放到目标ActivityStack的顶部
mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "sourceTaskToFront");
} else if (mDoResume) {
// 到这里说目标task已经在目标ActivityStack的顶部了,所以把把目标ActivityStack移动到最前面
mTargetStack.moveToFront("sourceStackToFront");
}
```
由于我们接下去需要对这个taskRecord进行操作,所以如果这个taskRecord已经被锁定了,那就返回。
接着先获取调用者的TaskRecord和ActivityStack,如果调用者要使用的taskRecord不在调用者所在ActivityStack顶部,那么我们从真正调用者那里获取一个合适的ActivityStack,这里不要被绕晕了,前面我们说过这里的mSourceRecord虽然叫调用者,但是由于前面有过可能把寻找到的复用栈赋值给它的操作,所以这里他不确定是不是原始的那个调用者,而mStartActivity这个变量才是原始的调用者,所以从这个原始调用者中计算下ActivityStack,之后把这个taskRecord转移到这个原始的ActivityStack中。这样ActivityStack和taskRecord就最终确定了,这时如果ActivityStack的顶部taskRecord还是不是需要的那个taskRecord,这是调用moveTaskToFrontLocked方法,这个方法在第二篇中有过分析,具体细节可以去那里看看,这里调用这个方法主要的作用是,一个是把需要的那个taskRecord放到顶部,第二把这个ActivityStack也放到他所在的ActivityDisplay的顶部,并设置为焦点ActivityStack,第三调用这个顶部Activity的onResume生命周期。
如果需要的taskRecord已经在ActivityStack顶部了,那么调用moveToFront方法把这个ActivityStack移动到顶部,并且设置为焦点ActivityStack。moveToFront方法前面也有过介绍,可以去前面的文章看下。好了,这个方法的前半部分结束了,我们看下后半部分方法:
```java
// 这种情况表示activity已经存在了,而且有clear_top标志,先清除,然后调用onNewIntent,onresume等
if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
// In this case, we are adding the activity to an existing task, but the caller has
// asked to clear that task if the activity is already running.
// 清除之上的activity
ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
mKeepCurTransition = true;
if (top != null) {
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
// 调用onNewIntent
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
// For paranoia, make sure we have correctly resumed the top activity.
mTargetStack.mLastPausedActivity = null;
if (mDoResume) { // 需要onResume,则调用onResume
mSupervisor.resumeFocusedStackTopActivityLocked();
}
ActivityOptions.abort(mOptions);
return START_DELIVERED_TO_TOP;
}
// FLAG_ACTIVITY_REORDER_TO_FRONT表示把任务栈中的这个Activity提到最上面
} else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
// 进入这个分支说明有复用,所以下面找到这个activity,提到最上面
// In this case, we are launching an activity in our own task that may already be
// running somewhere in the history, and we want to shuffle it to the front of the
// stack if so.
// 在task的activity集合中寻找和参数activity一样的ActivityRecord
final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
if (top != null) { // 找到的话
final TaskRecord task = top.getTask(); // 或者找到的这个Activity的task
task.moveActivityToFrontLocked(top); // 把找到的activity移动到它所在task的顶部
top.updateOptionsLocked(mOptions);
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
// 调用onNewIntent
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
mTargetStack.mLastPausedActivity = null;
if (mDoResume) { // 如果需要调用onresume
mSupervisor.resumeFocusedStackTopActivityLocked();
}
return START_DELIVERED_TO_TOP;
}
```
当mAddingToTask为false,启动模式是FLAG_ACTIVITY_CLEAR_TOP的时候,这里的逻辑前面我们已经遇到好几次了,寻找是否有一样的Activity,如果有的话清除他之上的Activity,然后如果返回有值的话,调用onNewIntent,如果需要onResume的话,调用onResume。
然后FLAG_ACTIVITY_REORDER_TO_FRONT这个启动标志表示要启动的Activity在任务栈中,但是可能不在顶部,所以需要获得他之后提到顶部,然后同样调用onNewIntent,有需要的话调用onResume。这里方法都比较简单就不展开讲了。
# 来自指定任务栈
至此,从调用者中获取任务栈的处理就完成了。我们接下去看下一个调用者有指定任务栈的情况,调用的方法是setTaskFromInTask:
```java
private int setTaskFromInTask() {
// The caller is asking that the new activity be started in an explicit
// task it has provided to us.
if (mSupervisor.isLockTaskModeViolation(mInTask)) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
mTargetStack = mInTask.getStack(); // 获取指定的ActivityStack
// Check whether we should actually launch the new activity in to the task,
// or just reuse the current activity on top.
ActivityRecord top = mInTask.getTopActivity(); // 获取这个ActivityStack的顶部Activity
if (top != null && top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId) {
// 到这里,说明顶部的这个Activity就是需要启动的Activity
if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask) {
// 如果是single_top,或则single_task.把这个task移动到ActivityStack的顶部
mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "inTaskToFront");
ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
// 表示调用者即是被调用者,不做什么,返回
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
// 调用onNewIntent
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
return START_DELIVERED_TO_TOP;
}
}
if (!mAddingToTask) { // 如果任务栈还未找到,把task移动到ActivityStack最前面
mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "inTaskToFront");
// We don't actually want to have this activity added to the task, so just
// stop here but still tell the caller that we consumed the intent.
ActivityOptions.abort(mOptions);
return START_TASK_TO_FRONT;
}
if (mLaunchBounds != null) { // 启动显示区域存在
mInTask.updateOverrideConfiguration(mLaunchBounds);
int stackId = mInTask.getLaunchStackId(); // 启动的ActivityStack
if (stackId != mInTask.getStackId()) { // 启动的ActivityStack不等于现在所在的ActivityStack
// 把指定的taskRecord加入到启动的ActivityStack
mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
DEFER_RESUME, "inTaskToFront");
stackId = mInTask.getStackId();
mTargetStack = mInTask.getStack();
}
if (StackId.resizeStackWithLaunchBounds(stackId)) {
mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
}
}
// task移动到顶部
mTargetStack.moveTaskToFrontLocked(
mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
// activity加入task
addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in explicit task " + mStartActivity.getTask());
return START_SUCCESS;
}
```
其实每个方法的整体思路都差不多,只不过在细节上有些区别。这里首先做了一些校验后,取出指定任务栈所在的ActivityStack,如果当前栈顶的Activity就是启动的Activity,那么在single_top和single_task的情况下,会把指定任务栈所在的ActivityStack移动到最前面,并且设为焦点ActivityStack,最后调用Activity的onNewIntent。
接着如果mAddingToTask为false的话,说明没有找到合适的任务栈,自然我们也不想把Activity加入这个指定任务栈,所以把指定任务栈调到最前面就返回了。
如果上面都没有返回,那么指定的这个taskRecord可以继续使用,接着看下这个taskRecord是什么类型的,如果和他现在所在的ActivityStack不是一个类型的话,那么调用reparent方法把他移动到该类型的ActivityStack中。
接着把确定的ActivityStack移动到顶部,并且设置为焦点。最后调用addOrReparentStartingActivity方法把要启动的Activity加入到指定的taskRecord中。
经过上面了一些情况处理,大部分启动的情况基本都包含了,这里最后else是除了上面之外的其他情况,调用的是setTaskToCurrentTopOrCreateNewTask方法。该方法是获取一个合适的ActivityStack后,取他顶部Activity所在的taskRecord,如果不存在就新建一个,根据google的注释,这种情况不太会发生,应该是作为一种最后的保护性手段。我们看下这个方法的实现:
```java
private void setTaskToCurrentTopOrCreateNewTask() {
// 获取目标ActivityStack
mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
mOptions);
if (mDoResume) { // 把目标ActivityStack移动到同一个displayId的集合中的顶部
mTargetStack.moveToFront("addingToTopTask");
}
final ActivityRecord prev = mTargetStack.topActivity(); // 获取顶部非finish的Activity
// 获取这个顶部activity的taskRecord。如果null,就创建一个taskRecord
final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
mIntent, null, null, true, mStartActivity.mActivityType);
// 把activity加入到这个task中
addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
mTargetStack.positionChildWindowContainerAtTop(task);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in new guessed " + mStartActivity.getTask());
}
```
这个方法首先是调用computeStackFocus获取一个合适的ActivityStack,如果需要显示的话,把这个ActivityStack移动到最前端,之后获取这个ActivityStack顶部的ActivityRecord,如果这个ActivityRecord有taskRecord,则把要启动的Activity加入这个taskRecord,否则新创建一个taskRecord,再把要启动的Activity加入他。
# 启动Activity
至此,如果上面启动Activty的过程中都能正确找到AcitityStack和taskRecord的话,那么下面开始进行启动的步骤了,如果有问题这里就会返回了。下面我们继续看后面启动的步骤:
```java
..................
if (mDoResume) {
// 获取要启动的Activity所属的task中最顶端正常显示的Activity
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
// 如果目标task不是聚焦的,那么我们不希望现在启动他,因为启动了也不是前台的
// 或者启动Activty的task的顶部是一个overlay的Activity,并且不是要启动的Activity,这种情况我们也
// 不希望启动,因为被覆盖了看不到
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
} else {
// 如果目标stack是可聚焦的,但是当前不是焦点,那么就把stack先放到最前面
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
// 启动这个Activity
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
....................
```
后面主要就是启动一个Activity了,这里代码可以看到如果需要显示的话,并且前面处理的activityStack等都正常的话,会调用这里resumeFocusedStackTopActivityLocked。我们接着主要跟着这个方法进一步分析后面的启动流程,其他异常的情况处理这里就不展开了,有兴趣的同学可以自己分析。在调用resumeFocusedStackTopActivityLocked方法前面,可以看到会先判断下如果这个启动的ActivityStack不是焦点,那么先要调用moveToFront把这个ActivityStack调到最前面并且设置为焦点,这个前面也分析过多次了,这里就提一下。好了,下面我们进入resumeFocusedStackTopActivityLocked方法继续分析启动流程:
```java
// 先判断下当前计算出的目标ActivityStack(即targetStack)是不是聚焦stack,是的话调用resumeTopActivityUncheckedLocked
// 不是的话,获取当前焦点stack的顶部Activity,
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
// 目标任务栈如果存在,且是焦点
if (targetStack != null && isFocusedStack(targetStack)) {
// 启动目标Activity
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
// 如果目标栈不存在,或者这个stack不是聚焦的。获取当前聚焦任务栈最上面一个活动的Activity
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
```
这个方法其实前面我们也看到过,比如找到一个复用的Activity的时候,如果Activity在顶部,就会调用没有参数的resumeFocusedStackTopActivityLocked这个方法,并且同样会调到这里,只不过传入的参数是null,来显示当前聚焦ActivityStack最上面一个界面,之前我们讲到这里就没继续跟进去了,现在终于来到了这里,我们可以继续接着这里往后讲了。这里不管怎么样,最后都会调用到resumeTopActivityUncheckedLocked这个方法,我们进一步跟进去看:
```java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
// 继续执行prev启动
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
mStackSupervisor.checkReadyForSleepLocked();
return result;
}
```
这个方法不长,每次启动的时候会把inResumeTopActivity这个变量置为true,说明当前执行onResume的流程,所以这个方法开通会判断如果当前正在执行onResume,就返回,否则下面继续调用resumeTopActivityInnerLocked方法,这个方法比较长,我们分段来看:
```java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
// 还没准备好,返回false
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
// Find the next top-most activity to resume in this stack that is not finishing and is
// focusable. If it is not focusable, we will fall into the case below to resume the
// top activity in the next focusable task.
// 这里next就是task栈顶元素,正常情况下是刚加入的即将要启动的Activity,当然比如栈顶是一个常驻元素的话就不一样了
// 同时这个方法的参数prev,正常情况下是和这里的next代表的是一样的,都是将要启动的Activity
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
final boolean hasRunningActivity = next != null;
final ActivityRecord parent = mActivityContainer.mParentActivity;
final boolean isParentNotResumed = parent != null && parent.state != ActivityState.RESUMED;
// 如果目前启动的这个Activity非空,但是他非resume状态,返回false。根据下面注释说明,一般情况系肯定是先调用父Activity正常起来了,才可能在调用子Activity
// 由于ActivityContainer关联着一个displayId,所以如果displayId是空,也要返回false
if (hasRunningActivity
&& (isParentNotResumed || !mActivityContainer.isAttachedLocked())) {
// Do not resume this stack if its parent is not resumed.
// TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
return false;
}
mStackSupervisor.cancelInitializingActivities();
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
// 保存下当前activity离开时,是否要通知的标志userLeaving
final boolean userLeaving = mStackSupervisor.mUserLeaving;
// 重置这个标志
mStackSupervisor.mUserLeaving = false;
// 如果当前没有要显示的Activity,进入这个分支
if (!hasRunningActivity) {
// There are no activities left in the stack, let's look somewhere else.
// 这个方法会寻找一个合适的界面返回
// 比如会寻找一个焦点返回。最后默认会回到主界面
return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
}
next.delayedResume = false;
// If the top activity is the resumed one, nothing to do.
// 栈顶的这个Activity已经resume过了,那也不要在处理什么了,返回
if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed " + next);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
final TaskRecord nextTask = next.getTask();
final TaskRecord prevTask = prev != null ? prev.getTask() : null;
if (prevTask != null && prevTask.getStack() == this &&
prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
if (prevTask == nextTask) {
prevTask.setFrontOfTask();
} else if (prevTask != topTask()) {
// This task is going away but it was supposed to return to the home stack.
// Now the task above it has to return to the home task instead.
final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
} else if (!isOnHomeDisplay()) {
return false;
} else if (!isHomeStack()){
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Launching home next");
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
}
}
// If we are sleeping, and there is no resumed activity, and the top
// activity is paused, well that is the state we want.
// 如果正在关机或者睡眠,并且栈顶的这个已经被停止了,就返回,启动了也没什么意义
if (mService.isSleepingOrShuttingDownLocked()
&& mLastPausedActivity == next
&& mStackSupervisor.allPausedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Going to sleep and all paused");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
// Make sure that the user who owns this activity is started. If not,
// we will just leave it as is because someone should be bringing
// another user's activities to the top of the stack.
// 启动这个Activity的userId找不到,返回
if (!mService.mUserController.hasStartedUserState(next.userId)) {
Slog.w(TAG, "Skipping resume of top activity " + next
+ ": user " + next.userId + " is stopped");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
// The activity may be waiting for stop, but that is no longer
// appropriate for it.
// 把这个将要启动的Activity从那些正在停止或者睡眠的集合中移除
mStackSupervisor.mStoppingActivities.remove(next);
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
// 从等待被显示的集合中移除,典型的就是将要启动的Activity
mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
// If we are currently pausing an activity, then don't do anything until that is done.
// 表示当前是否有正在处理停止的Activity,如果有的话,就返回false
if (!mStackSupervisor.allPausedActivitiesComplete()) {
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
"resumeTopActivityLocked: Skip resume: some activity pausing.");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
// 获取一个wakeLock,保证执行启动ACtivity过程中,系统不会休眠
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
```
这里是第一段代码。这段代码还没涉及到启动的核心内容,主要是做一些检查。首先取出当前要启动的ActivityStack的顶部Activity,由于前面我们已经把要启动的Activity加入的,所以正常情况下栈顶元素就是要启动的Activity。然后做一些判断,比如ActivtyStack如果没有attach,就返回。取出栈顶元素为空就返回。栈顶元素的eonresume都处理过了,就返回。将要关机或者睡眠了就返回。栈顶这个Activity的userId和当前的不一样就返回。当前正在处理onPause,那么也要等处理完后在继续。凡此种种,一系列的检查后,最后调用setLaunchSource方法:
```java
void setLaunchSource(int uid) {
mLaunchingActivity.setWorkSource(new WorkSource(uid));
}
```
这个是让系统获取一个WakeLock,让系统在启动Activity过程中不要休眠,这个了解一下就好。经过这些检查我们看下一段代码:
```java
boolean lastResumedCanPip = false;
// 获取之前最后一次的焦点stack
final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
// 如果之前焦点stack非空,并且不是现在的这个
if (lastFocusedStack != null && lastFocusedStack != this) {
// So, why aren't we using prev here??? See the param comment on the method. prev doesn't
// represent the last resumed activity. However, the last focus stack does if it isn't null.
// 获取之前最后一次的resume的Activity
final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity;
// 看下之前的这个Activity是不是支持画中画
lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
"resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */);
}
// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
// to be paused, while at the same time resuming the new resume activity only if the
// previous activity can't go into Pip since we want to give Pip activities a chance to
// enter Pip before resuming the next activity.
// true的话,需要等待先pause,在resume
final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
&& !lastResumedCanPip;
// 停止所有屏幕中stack的resume的Activity(除了当前焦点stack)
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
// 当前这个Stack的resume的Activity不为空
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
// 停止当前这个Activity的resume的Activity
pausing |= startPausingLocked(userLeaving, false, next, false);
}
// 如果正在停止Activity,并且不是在停止的时候就要启动这个待启动的Activity
if (pausing && !resumeWhilePausing) {
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;
} else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
//栈顶就是要显示的Activity,后面也不需要处理什么,return
// It is possible for the activity to be resumed when we paused back stacks above if the
// next activity doesn't have to wait for pause to complete.
// So, nothing else to-do except:
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
// If the most recent activity was noHistory but was only stopped rather
// than stopped+finished because the device went to sleep, we need to make
// sure to finish it as we're making a new activity topmost.
// 对于无历史的activity,在睡眠的时候,并且当前也没有finish的时候,会被finish掉
if (mService.isSleepingLocked() && mLastNoHistoryActivity != null &&
!mLastNoHistoryActivity.finishing) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"no-history finish of " + mLastNoHistoryActivity + " on new resume");
// 请求finish
requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
null, "resume-no-history", false);
mLastNoHistoryActivity = null;
}
// 这里prev是要启动的Activity,如果非空。但是不等于当前栈顶Activity(正常启动情况会相等)
// 如果不等的话,会把要启动的加入到将要显示的集合中
if (prev != null && prev != next) {
if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
&& next != null && !next.nowVisible) {
mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev);
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Resuming top, waiting visible to hide: " + prev);
} else {
// The next activity is already visible, so hide the previous
// activity's windows right now so we can show the new one ASAP.
// We only do this if the previous is finishing, which should mean
// it is on top of the one being resumed so hiding it quickly
// is good. Otherwise, we want to do the normal route of allowing
// the resumed activity to be shown so we can decide if the
// previous should actually be hidden depending on whether the
// new one is found to be full-screen or not.
if (prev.finishing) {
prev.setVisibility(false);
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Not waiting for visible to hide: " + prev + ", waitingVisible="
+ mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
+ ", nowVisible=" + next.nowVisible);
} else {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Previous already visible but still waiting to hide: " + prev
+ ", waitingVisible="
+ mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
+ ", nowVisible=" + next.nowVisible);
}
}
}
// Launching this app's activity, make sure the app is no longer
// considered stopped.
// 通过PMS修改这个应用包的一些属性设置
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);
}
// We are starting up the next activity, so tell the window manager
// that the previous one will be hidden soon. This way it can know
// to ignore it when computing the desired screen orientation.
// 一些动画相关的
boolean anim = true;
if (prev != null) {
if (prev.finishing) {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare close transition: prev=" + prev);
if (mNoAnimActivities.contains(prev)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
? TRANSIT_ACTIVITY_CLOSE
: TRANSIT_TASK_CLOSE, false);
}
prev.setVisibility(false);
} else {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare open transition: prev=" + prev);
if (mNoAnimActivities.contains(next)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
? TRANSIT_ACTIVITY_OPEN
: next.mLaunchTaskBehind
? TRANSIT_TASK_OPEN_BEHIND
: TRANSIT_TASK_OPEN, false);
}
}
} else {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
if (mNoAnimActivities.contains(next)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
}
}
Bundle resumeAnimOptions = null;
if (anim) {
ActivityOptions opts = next.getOptionsForTargetActivityLocked();
if (opts != null) {
resumeAnimOptions = opts.toBundle();
}
next.applyOptionsLocked();
} else {
next.clearOptionsLocked();
}
```
这段代码开始有个变量resumeWhilePausing,这个变量表示当在执行停止操作的时候,是否可以onResume,这个和FLAG_RESUME_WHILE_PAUSING这个标志有关,如果设置了这个标识就说明可以在有onPause的时候执行onresume,另外和之前最后一次的resume的Activity是否可以画中画,按照google的说明,如果这个Activity是可以画中画,那么我们要等他都处理完成了再开启onResume,所以只有不支持画中画的时候下一个启动的Activity才能在有停止操作的时候继续启动。
到这里前面的处理基本都完成了,现在在启动目标Activity前,先要停止之前的Activity,这里首先调用pauseBackStacks这个方法停止所有后台Activity中的Resume状态的Activity。
```java
// 停止所有屏幕中stack的resume的Activity(除了当前焦点stack)
boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
boolean someActivityPaused = false;
// 遍历当前所有屏幕
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
// 取出每个屏幕的所有ActivityStack
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
// 遍历所有ActivityStack
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
// 取出每个ActivityStack
final ActivityStack stack = stacks.get(stackNdx);
// 如果非当前焦点stack,同时他的resume的Activity不为空(即这个stack有resume的activity)
// 那么就停止这个resume的Activity
if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + stack.mResumedActivity);
// 停止这个stack的resume的Activity
someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
dontWait);
}
}
}
return someActivityPaused;
}
```
这个方法遍历所有屏幕中的非焦点ActivityStack,如果他的resumedActivity非空,然后调用startPausingLocked方法,我们继续看下这个方法:
```java
// 停止这个stack的resume的Activity
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean pauseImmediately) {
// 一开始进来这里,mPausingActivity是空,后面会赋值
if (mPausingActivity != null) {
if (!mService.isSleepingLocked()) {
completePauseLocked(false, resuming);
}
}
// mResumedActivity就是resume的Activity,也就是即将要停止的Activity,先赋值给prev
ActivityRecord prev = mResumedActivity;
// 如果没有要停止的Activity就return
if (prev == null) {
if (resuming == null) {
Slog.wtf(TAG, "Trying to pause when nothing is resumed");
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
return false;
}
// 这个stack没有父ActivityRecord。说明他是顶层的ActivityRecord
// 遍历所有的ActivityStack,如果是这个要停止的ActivityRecord的字Activty
// 调用onpause
if (mActivityContainer.mParentActivity == null) {
// Top level stack, not a child. Look for child stacks.
mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping, resuming,
pauseImmediately);
}
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
mResumedActivity = null; // 当前resume的因为要被onpause了,所以置空
mPausingActivity = prev; // 当前要停止的Activity置为prev
mLastPausedActivity = prev; // 最后一个被停止的Activity置为prev
mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
prev.state = ActivityState.PAUSING; // 这个要停止的Activity状态被置为pausing了
prev.getTask().touchActiveTime();
clearLaunchTime(prev);
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
if (mService.mHasRecents
&& (next == null || next.noDisplay || next.getTask() != prev.getTask()
|| uiSleeping)) {
prev.mUpdateTaskThumbnailWhenHidden = true;
}
stopFullyDrawnTraceIfNeeded();
mService.updateCpuStats();
// 如果这个界面是存在的,即ProcessRecord和ApplicationProxy都是有的,调用里面的schedulePauseActivity方法
if (prev.app != null && prev.app.thread != null) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
prev.userId, System.identityHashCode(prev),
prev.shortComponentName);
mService.updateUsageStats(prev, false);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, pauseImmediately);
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
// 报错了,这些变量清掉。正常执行的话不会清
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
} else {
// 到这里说明没有这个进程,所以清掉
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
// 非睡眠的情况下,还是要获得锁,保证后面启动Activity不受影响
if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
mStackSupervisor.acquireLaunchWakelock();
}
// 到这里说明上面执行都正常了,说明一个Activity已经被onpause了
if (mPausingActivity != null) {
if (!uiSleeping) {
prev.pauseKeyDispatchingLocked();
} else if (DEBUG_PAUSE) {
Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
}
if (pauseImmediately) {
// If the caller said they don't want to wait for the pause, then complete
// the pause now.
completePauseLocked(false, resuming);
return false;
} else {
schedulePauseTimeout(prev);
return true;
}
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
// onpause失败才会进入到这个,而resuming是即将要启动的Activity
// 如果没有即将要启动的Activity,那么会调用resumeFocusedStackTopActivityLocked
// 这个方法自动选择一个返回到的界面
if (resuming == null) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
return false;
}
}
```
这里首先如果mPausingActivity非空的话,回调用completePauseLocked方法把他加入stop集合,我们知道如果正常一个全屏的Activity一般在启动了其他Activity后,他会调用onPause方法,之后就会在调用onStop方法,这里调用onStop前的处理就是从completePauseLocked开始的:
```java
private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
// 把mPausingActivity赋值给prev
ActivityRecord prev = mPausingActivity;
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
//
if (prev != null) {
final boolean wasStopping = prev.state == STOPPING;
prev.state = ActivityState.PAUSED;
if (prev.finishing) { // 这个activity准备finish
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
} else if (prev.app != null) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
+ " wasStopping=" + wasStopping + " visible=" + prev.visible);
// 从等待显示的集合中删除他
if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) {
if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
"Complete pause, no longer waiting: " + prev);
}
// 被延迟启动的Activity,现在已经pause好了,可以重启启动了
if (prev.deferRelaunchUntilPaused) {
// Complete the deferred relaunch that was waiting for pause to complete.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
prev.relaunchActivityLocked(false /* andResume */,
prev.preserveWindowOnDeferredRelaunch);
} else if (wasStopping) {
// We are also stopping, the stop request must have gone soon after the pause.
// We can't clobber it, because the stop confirmation will not be handled.
// We don't need to schedule another stop, we only need to let it happen.
prev.state = STOPPING;
} else if ((!prev.visible && !hasVisibleBehindActivity())
|| mService.isSleepingOrShuttingDownLocked()) {
// 如果这个正在停止的Activity不可见,或者锁屏休眠了,会执行addToStopping方法
// Clear out any deferred client hide we might currently have.
prev.setDeferHidingClient(false);
// If we were visible then resumeTopActivities will release resources before
// stopping.
// 这个方法会把相关Activity加入到stop的集合中,并根据情况看要不要马上执行onstop和finish的方法
addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);
}
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
prev = null;
}
// It is possible the activity was freezing the screen before it was paused.
// In that case go ahead and remove the freeze this activity has on the screen
// since it is no longer visible.
if (prev != null) {
prev.stopFreezingScreenLocked(true /*force*/);
}
mPausingActivity = null;
}
...................
}
```
这里可以看到如果当前有需要停止的Activity,会有一系列的判断,我们看最后的一个判断会调用addToStopping方法把他加入一个stop的集合,前台条件是这个Activity的window是否是透明的,如果主题设置透明的Activity就不会执行onStop方法了,否则会在这里加入stop集合后,后面再执行onStop方法。我们看下方法:
```java
void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
mStackSupervisor.mStoppingActivities.add(r);
}
// If we already have a few activities waiting to stop, then give up
// on things going idle and start clearing them out. Or if r is the
// last of activity of the last task the stack will be empty and must
// be cleared immediately.
// 如果等待stop的Activity集合的数量超过3个(MAX_STOPPING_TO_FORCE这里定义为3)
// 或者这里的r是task中的顶端同时task是stack中的最后一个。
// 会触发下面执行stop或者finish相关集合中Activity的流程
boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
|| (r.frontOfTask && mTaskHistory.size() <= 1);
if (scheduleIdle || forceIdle) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle="
+ forceIdle + "immediate=" + !idleDelayed);
if (!idleDelayed) {
// 处理等待stop集合
mStackSupervisor.scheduleIdleLocked();
} else {
mStackSupervisor.scheduleIdleTimeoutLocked(r);
}
} else {
mStackSupervisor.checkReadyForSleepLocked();
}
}
```
这个方法我们看到开始就是把这个ActivityRecord加入到了一个集合中,之后调用Activity的onStop的方法会从这个集合中取出,后面说到这个地方的时候我们在看。值得注意的是这个方法后面一部分。后面部分的意思是,如果这个stop集合的数量大于MAX_STOPPING_TO_FORCE这个值了(这个值是3),或者历史任务栈小于等于1个并且
这个ActivityRecord是任务栈中的顶端,会执行stop或者finish方法,调用的是scheduleIdleLocked方法,这里就不跟进去看了,知道这个方法做什么的就可以了。这里是自动触发的,有时候我们可能会遇到一些后台被杀的问题,这里的逻辑也可以排查下。好了,跳得太远了,我们回到startPausingLocked方法,继续讲下去。
前面讲到把ActivityStack中记录的最后一个pause的Activity通过调用addToStopping可能会加入一个Stop集合中,接着就要pause当前resume的Activity了。当前resume的Activity保存在mResumedActivity中,如果是空那就没什么要做的了,返回即可。
接着由于现在是要停止每个ActivyStack中resume的Activity,如果这个ActivityStack有子ActivityStack的话,那么肯定也要被停止,所以在停止自己的mResumedActivity前,前停止子ActivityStack中的,调用的pauseChildStacks方法:
```java
void pauseChildStacks(ActivityRecord parent, boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean dontWait) {
// TODO: Put all stacks in supervisor and iterate through them instead.
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack.mResumedActivity != null &&
stack.mActivityContainer.mParentActivity == parent) {
stack.startPausingLocked(userLeaving, uiSleeping, resuming, dontWait);
}
}
}
}
```
可以看到遍历屏幕的所有ActivityStack,如果是子Activity的话,还是调用startPausingLocked这个方法,相信大家都能理解。我们回到前面。
之后更新下ActivityStack中保存的状态,比如想mResumedActivity,mPausingActivity这些对象现在都已经改变了,更新他们当前的值,当然要停止的Activity的状态也更新为PAUSING。之后就要调用schedulePauseActivity方法执行pause操作了,这个方法是跨进程的binder,会在目前进程中执行,这么暂时先不说,我们知道接下去回到目前进程中执行就可以,后面跨进程的会统一说。
到这里已经把目前要停止的Activity都停止了,我们回到resumeTopActivityInnerLocked方法。前面说过了,如果当前正在执行pause操作,并且resumeWhilePausing是false,那就要等到pause完成后再执行resume,现在就退出。如果当前resumeWhilePausing就是将要启动Activity那么也不用操作了,退出。
接着有一种Activity是不会出现在最近任务的历史中的,这种是在启动时候带FLAG_ACTIVITY_NO_HISTORY这个标签的,对于这种类型的Activity来说,会在系统进入睡眠的时候被finis,调用的是requestFinishActivityLocked方法:
```java
// 开始finish某个Activity
final boolean requestFinishActivityLocked(IBinder token, int resultCode,
Intent resultData, String reason, boolean oomAdj) {
// 通过IApplicationToken.Stub获取对应的ActivityRecord
ActivityRecord r = isInStackLocked(token);
if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(TAG_STATES,
"Finishing activity token=" + token + " r="
+ ", result=" + resultCode + ", data=" + resultData
+ ", reason=" + reason);
if (r == null) {
return false;
}
// 继续调用finish
finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
return true;
}
```
这里根据token取出ActivityRecord后,继续调用finishActivityLocked方法。这个我们也不跟进了,这个方法也比较长,也是设计binder跨进程的生命周期方法,我们后面文章会专门讲这些跨进程的方法。这个只要知道会调用finish,即会执行Activity的onDestory方法。
我们回到resumeTopActivityInnerLocked方法。如果到目前都一切正常的话,要启动的这个Activity会被加入到mActivitiesWaitingForVisibleActivity集合中,这个是在后面用户被显示的Activity,后面的流程我们会看到他调用的地方,这里先有个印象就好。接着把要启动的包名,userId等传给PMS做一些校验检查,然后设置启动动画后,我们看下这个方法下一部分代码:
```java
ActivityStack lastStack = mStackSupervisor.getLastStack();
// 如果将要启动Activity非空,即已经存在了
if (next.app != null && next.app.thread != null) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
+ " stopped=" + next.stopped + " visible=" + next.visible);
// If the previous activity is translucent, force a visibility update of
// the next activity, so that it's added to WM's opening app list, and
// transition animation can be set up properly.
// For example, pressing Home button with a translucent activity in focus.
// Launcher is already visible in this case. If we don't add it to opening
// apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
// TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
final boolean lastActivityTranslucent = lastStack != null
&& (!lastStack.mFullscreen
|| (lastStack.mLastPausedActivity != null
&& !lastStack.mLastPausedActivity.fullscreen));
// This activity is now becoming visible.
if (!next.visible || next.stopped || lastActivityTranslucent) {
next.setVisibility(true);
}
// schedule launch ticks to collect information about slow apps.
next.startLaunchTickingLocked();
// 获取当前的焦点Activity(应该是新activity启动前那个)
ActivityRecord lastResumedActivity =
lastStack == null ? null :lastStack.mResumedActivity;
// 获取启动的activity的状态
ActivityState lastState = next.state;
mService.updateCpuStats();
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)");
// 设置当前stack的mResumedActivity为将要启动的activity,并修改activity的state为resume
// 把activity对应的task加入最近任务集合中
setResumedActivityLocked(next, "resumeTopActivityInnerLocked");
mService.updateLruProcessLocked(next.app, true, null);
updateLRUListLocked(next);
mService.updateOomAdjLocked();
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order.
boolean notUpdated = true;
if (mStackSupervisor.isFocusedStack(this)) {
final Configuration config = mWindowManager.updateOrientationFromAppTokens(
mStackSupervisor.getDisplayOverrideConfiguration(mDisplayId),
next.mayFreezeScreenLocked(next.app) ? next.appToken : null, mDisplayId);
if (config != null) {
next.frozenBeforeDestroy = true;
}
notUpdated = !mService.updateDisplayOverrideConfigurationLocked(config, next,
false /* deferResume */, mDisplayId);
}
// 这里notUpdated是通过上面updateDisplayOverrideConfigurationLocked来赋值的
// 这里表示不是新启动一个activity,而是屏幕配置变化后重新启动了,所以下面这个if
if (notUpdated) {
// The configuration update wasn't able to keep the existing
// instance of the activity, and instead started a new one.
// We should be all done, but let's just make sure our activity
// is still at the top and schedule another run if something
// weird happened.
// 获取当前顶部activity
ActivityRecord nextNext = topRunningActivityLocked();
if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
"Activity config changed during resume: " + next
+ ", new next: " + nextNext);
// 如果和焦点的不一样
if (nextNext != next) {
// Do over!
// 这个方法最终会调用resumeFocusedStackTopActivityLocked
// 最后也会走到这里
mStackSupervisor.scheduleResumeTopActivities();
}
if (!next.visible || next.stopped) {
next.setVisibility(true);
}
next.completeResumeLocked();
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
```
这部分显示更新一些状态后,调用setResumedActivityLocked来设置当前这个ActivityStack的mResumedActivity,我们看下这个方法:
```java
void setResumedActivityLocked(ActivityRecord r, String reason) {
// TODO: move mResumedActivity to stack supervisor,
// there should only be 1 global copy of resumed activity.
mResumedActivity = r; // 把stack的mResumed的Activity设置为要启动的activity
r.state = ActivityState.RESUMED; // activity的状态设置为resume
mService.setResumedActivityUncheckLocked(r, reason); // 更新AMS的一些状态
final TaskRecord task = r.getTask(); // 获取要启动activity的task
task.touchActiveTime();
mRecentTasks.addLocked(task); // 把要启动的activity任务加入最近任务集合中
}
```
可以看到把要启动的这个Activity设置给mResumedActivity,然后更新他的状态为RESUMED。之后把他所在的task加入最近任务的集合mRecentTasks。
回到前面方法,之后调用updateDisplayOverrideConfigurationLocked,这个方法表示新的config参数是否有更新,如果没有更新,那么就说明有问题了,所以也不进一步执行下去了。这时候先看下ActivityStack的顶部Activity是否还是同一个,如果不是的话,调用scheduleResumeTopActivities方法,最终会调到resumeFocusedStackTopActivityLocked,重新显示当前顶部Activity。最后返回,也不往下执行了。
我们看这个方法的最后一段代码:
```java
try {
// Deliver all pending results.
ArrayList<ResultInfo> a = next.results;
// 如果有result,会调用scheduleSendResult
if (a != null) {
final int N = a.size();
if (!next.finishing && N > 0) {
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Delivering results to " + next + ": " + a);
next.app.thread.scheduleSendResult(next.appToken, a);
}
}
// 如果有newintens,调用scheduleNewIntent
if (next.newIntents != null) {
next.app.thread.scheduleNewIntent(
next.newIntents, next.appToken, false /* andPause */);
}
// Well the app will no longer be stopped.
// Clear app token stopped state in window manager if needed.
next.notifyAppResumed(next.stopped);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
System.identityHashCode(next), next.getTask().taskId,
next.shortComponentName);
next.sleeping = false;
mService.showUnsupportedZoomDialogIfNeededLocked(next);
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(mService.mTopProcessState);
next.clearOptionsLocked();
// 最后会调用scheduleResumeActivity
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next);
} catch (Exception e) {
// Whoops, need to restart this activity!
if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
+ lastState + ": " + next);
next.state = lastState;
if (lastStack != null) {
lastStack.mResumedActivity = lastResumedActivity;
}
Slog.i(TAG, "Restarting because process died: " + next);
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
mStackSupervisor.isFrontStackOnDisplay(lastStack)) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwitch */);
}
mStackSupervisor.startSpecificActivityLocked(next, true, false);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
// From this point on, if something goes wrong there is no way
// to recover the activity.
try {
next.completeResumeLocked();
} catch (Exception e) {
// If any exception gets thrown, toss away this
// activity and try the next one.
Slog.w(TAG, "Exception thrown during resume of " + next, e);
requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
"resume-exception", true);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
} else {
// Whoops, need to restart this activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwich */);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
// 到这里说明这个进程不存在,那么要启动他
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
```
如果前面都没什么问题的话就执行到这里。这里首先如果有需要回复给调用者的话,会从启动Activity中取出results集合,然后调用scheduleSendResult方法,这是个跨进程的binder我们后面说,这个最终会回调调用者的onActivityResult方法。如果启动的Activity需要回调onNewIntent的话,同样是一个binder通信方法scheduleNewIntent,这个之前我们也遇到过,这里也暂且不说。
最后以上都处理完了,就会执行scheduleResumeActivity这个方法了,这个方法是回调对方进场的onResume方法,我们后面说。至此,如果启动一个已经存在的Activity的话,AMS这里暂时告一段落了。下面会到启动者进程中区执行。我们这里先放一放,不继续往下走,我们再看下如果当前不存在需要启动的Activity的话怎么处理。
# 开启一个新Activity
这里会走到最后一个else中,执行startSpecificActivityLocked方法,我们跟进去看一下:
```java
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
// 获取启动的这个进程ProcessRecord
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
// 如果已经有这个进程了
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.versionCode,
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.
}
// 到这里说明没有这个进程,首先要启动Process
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
```
这里首先会根据进程名从AMS的getProcessRecordLocked方法获取一个进程的ProcessRecord:
```java
final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
if (uid == SYSTEM_UID) {
// The system gets to run in any process. If there are multiple
// processes with the same uid, just pick the first (this
// should never happen).
SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(processName);
if (procs == null) return null;
final int procCount = procs.size();
for (int i = 0; i < procCount; i++) {
final int procUid = procs.keyAt(i);
if (UserHandle.isApp(procUid) || !UserHandle.isSameUser(procUid, uid)) {
// Don't use an app process or different user process for system component.
continue;
}
return procs.valueAt(i);
}
}
// 从map中获取ProcessRecord
ProcessRecord proc = mProcessNames.get(processName, uid);
if (false && proc != null && !keepIfLarge
&& proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY
&& proc.lastCachedPss >= 4000) {
// Turn this condition on to cause killing to happen regularly, for testing.
if (proc.baseProcessTracker != null) {
proc.baseProcessTracker.reportCachedKill(proc.pkgList, proc.lastCachedPss);
}
proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true);
} else if (proc != null && !keepIfLarge
&& mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
&& proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
if (DEBUG_PSS) Slog.d(TAG_PSS, "May not keep " + proc + ": pss=" + proc.lastCachedPss);
if (proc.lastCachedPss >= mProcessList.getCachedRestoreThresholdKb()) {
if (proc.baseProcessTracker != null) {
proc.baseProcessTracker.reportCachedKill(proc.pkgList, proc.lastCachedPss);
}
proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true);
}
}
return proc;
}
```
在AMS中会维护所有进程的一个Map,每个进程在AMS中是一个ProcessRecord对象,该对象中有具体那个对象的一个binder代理,通过这个代理就可以和具体的进程通信了。
这个方法把系统uid和普通uid获取ProcessRecord的方法区分了开来,根据注释的说明系统可以在任何的进程中运行,所以担心会获取同名的进程,所以还需要用uid来区分,普通进程就直接获取他需要的进程名就可以了。这里获取ProcessRecord后返回。我们回到startSpecificActivityLocked方法。
# 开启一个新进程
如果当前AMS有有这个进程,那么就说明之前有启动过,现在就需要创建一个Activity来启动,调用realStartActivityLocked方法。如果还没启动过那么先要启动一个进程,通过AMS的startProcessLocked方法。我们先看下前面的realStartActivityLocked方法:
```java
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
// 要启动一个activity,先检查是否pause的任务都完成了,没完成就return
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;
}
.........................
// 获取这个进程的信息
final int applicationInfoUid =
(r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) {
Slog.wtf(TAG,
"User ID for activity changing for " + r
+ " appInfo.uid=" + r.appInfo.uid
+ " info.ai.uid=" + applicationInfoUid
+ " old=" + r.app + " new=" + app);
}
r.app = app;
app.waitingToKill = null;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);
int idx = app.activities.indexOf(r);
// 看下这个进程下面是否已经有了这个ActivityRecord
// 如果没有就加入这个ActivityRecord
if (idx < 0) {
app.activities.add(r);
}
mService.updateLruProcessLocked(app, true, null);
mService.updateOomAdjLocked();
// 获取这个Activity的task
final TaskRecord task = r.getTask();
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
}
// 通过这个Activity的task获取ActivityStack
final ActivityStack stack = task.getStack();
try {
// 如果没有ApplicationProxy,报错
if (app.thread == null) {
throw new RemoteException();
}
List<ResultInfo> results = null;
List<ReferrerIntent> newIntents = null;
// 设置回复result和newIntent
if (andResume) {
// We don't need to deliver new intents and/or set results if activity is going
// to pause immediately after launch.
results = r.results;
newIntents = r.newIntents;
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Launching: " + r + " icicle=" + r.icicle + " with results=" + results
+ " newIntents=" + newIntents + " andResume=" + andResume);
EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId,
System.identityHashCode(r), task.taskId, r.shortComponentName);
if (r.isHomeActivity()) {
// Home process is the root process of the task.
//如果是luncher界面的话,从第0个Activity中获取ProcessRecord
mService.mHomeProcess = task.mActivities.get(0).app;
}
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
r.sleeping = false;
r.forceNewConfig = false;
mService.showUnsupportedZoomDialogIfNeededLocked(r);
mService.showAskCompatModeDialogLocked(r);
r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
ProfilerInfo profilerInfo = null;
if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
if (mService.mProfileProc == null || mService.mProfileProc == app) {
mService.mProfileProc = app;
final String profileFile = mService.mProfileFile;
if (profileFile != null) {
ParcelFileDescriptor profileFd = mService.mProfileFd;
if (profileFd != null) {
try {
profileFd = profileFd.dup();
} catch (IOException e) {
if (profileFd != null) {
try {
profileFd.close();
} catch (IOException o) {
}
profileFd = null;
}
}
}
profilerInfo = new ProfilerInfo(profileFile, profileFd,
mService.mSamplingInterval, mService.mAutoStopProfiler,
mService.mStreamingOutput);
}
}
}
app.hasShownUi = true;
app.pendingUiClean = true;
app.forceProcessStateUpTo(mService.mTopProcessState);
// Because we could be starting an Activity in the system process this may not go across
// a Binder interface which would create a new Configuration. Consequently we have to
// always create a new Configuration here.
final MergedConfiguration mergedConfiguration = new MergedConfiguration(
mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
r.setLastReportedConfiguration(mergedConfiguration);
// 启动这个Activity.通过AIDL的binder后,最终会走到ActivityThread的内部类ApplicationThread
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global and
// override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
......................
return true;
}
```
首先要启动一个新的Activity,要等当前所有的pause执行都完成后才可以启动。之后,由于现在进程是存在的,所以可以把进程赋值给要启动的这个ActivityRecord。在每个ProcessRecord中会保存当前在该进程中运行着的Activity,所以如果该进程中还没有这个要启动的Activity,就把他加入。之后如果有要回复给调用者的result数据以及回调onNewIntent数据,也要取出后面会一起传入要启动的进程。在AMS中,mHomeProcess变量是保存着桌面的进程的,所以如果这个要启动的Activity是桌面Activity,那么就取出桌面的进程赋值给AMS的mHomeProcess。一切都就绪都可以把这些数据通过scheduleLaunchActivity方法传给要启动的进程了。这个方法也是一个binder通信,我们后面再说。这样如果进程存在的情况下,AMS这里启动一个Activity的操作就完成了。下面我们回去再看下如果进程不存在的时候是怎么创建进程的。
前面说了,进程不存在的时候会调用AMS的startProcessLocked方法:
```java
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
```
这里会继续调用startProcessLocked:
```java
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
long startTime = SystemClock.elapsedRealtime();
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
checkTime(startTime, "startProcess: after getProcessRecord");
if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
// If we are in the background, then check to see if this process
// is bad. If so, we will just silently fail.
if (mAppErrors.isBadProcessLocked(info)) {
if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
+ "/" + info.processName);
return null;
}
} else {
// When the user is explicitly starting a process, then clear its
// crash count so that we won't make it bad until they see at
// least one crash dialog again, and make the process good again
// if it had been bad.
if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
+ "/" + info.processName);
mAppErrors.resetProcessCrashTimeLocked(info);
if (mAppErrors.isBadProcessLocked(info)) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
UserHandle.getUserId(info.uid), info.uid,
info.processName);
mAppErrors.clearBadProcessLocked(info);
if (app != null) {
app.bad = false;
}
}
}
} else {
// If this is an isolated process, it can't re-use an existing process.
app = null;
}
// We don't have to do anything more if:
// (1) There is an existing application record; and
// (2) The caller doesn't think it is dead, OR there is no thread
// object attached to it so we know it couldn't have crashed; and
// (3) There is a pid assigned to it, so it is either starting or
// already running.
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName
+ " app=" + app + " knownToBeDead=" + knownToBeDead
+ " thread=" + (app != null ? app.thread : null)
+ " pid=" + (app != null ? app.pid : -1));
if (app != null && app.pid > 0) {
if ((!knownToBeDead && !app.killed) || app.thread == null) {
// We already have the app running, or are waiting for it to
// come up (we have a pid but not yet its thread), so keep it.
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
// If this is a new package in the process, add the package to the list
// 一个进程可以有多个包名
app.addPackage(info.packageName, info.versionCode, mProcessStats);
checkTime(startTime, "startProcess: done, added package to proc");
// 虽然这个thread为null,但是按照注释的意思是,其他的进程特征都符合,比如有pid。所以可以被认为是一个正常的进程返回
return app;
}
// An application record is attached to a previous process,
// clean it up now.
if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app);
checkTime(startTime, "startProcess: bad proc running, killing");
killProcessGroup(app.uid, app.pid);
handleAppDiedLocked(app, true, true);
checkTime(startTime, "startProcess: done killing old proc");
}
String hostingNameStr = hostingName != null
? hostingName.flattenToShortString() : null;
if (app == null) { // 如果app为null,新建一个
checkTime(startTime, "startProcess: creating new process record");
// 创建ProcessRecord对象
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
return null;
}
app.crashHandler = crashHandler;
checkTime(startTime, "startProcess: done creating new process record");
} else { // 不为空的话,看下包名是不是新的,新的话,把这个包名加入到map中
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, info.versionCode, mProcessStats);
checkTime(startTime, "startProcess: added package to existing proc");
}
// If the system is not ready yet, then hold off on starting this
// process until it is.
if (!mProcessesReady
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
"System not ready, putting on hold: " + app);
checkTime(startTime, "startProcess: returning with proc on hold");
return app;
}
checkTime(startTime, "startProcess: stepping in to startProcess");
// 到这里,说明这个Process实际是不存在的,现在开始创建
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
checkTime(startTime, "startProcess: done starting proc!");
return (app.pid != 0) ? app : null;
}
```
首先会在通过getProcessRecordLocked方法获取下进程,除了做一些校验外,这里的注释特别说明了一下,可以直接返回不用做任何操作。比如确实能获取一个ProcessRecord,他的pid也是大于0的,说明是创建成功。但是调用者传过来的参数认为是正常的同时该进程也没有被杀的情况,或者他的代理对象是空的时候,这两种情况可以不用再创建新检查,直接返回。我们知道到这里方法在前面有提到过,是因为判断没有这个进程的存在所以会执行这个方法用来创建新进程,为什么会这样呢?我的理解是,因为系统是非常复杂的,通过AMS和客户端通过binder通信,有些是同步的,有些是异步的,所以可能存在异步的过程中,正常一个进程还在创建但是没有创建完成的情况,所以这里可能调用者知道会有这种情况所以传过来的参数是任务这个进程是正常的,另外如果app.thread == null这句话,说明ProcessRecord是存在的,但是他的代理thread为null,这个就可能是客户端那边还在初始化,所以还没有给AMS回复。接下去我们会讲到在客户端创建进程的过程,可以看到客户端创建一个进程需要做一系列的动作,然后再通知AMS,AMS收到通知后再给ProcessRecord赋值,所以这里直接返回不需要做什么操作,后面等进程初始化完成了自然还有后续的动作。这里就是对于我个人的理解。当然如果系统当前还没准备好的话,也会直接返回,这个自不必说。
好了,如果确实没有进程的话,会调用startProcessLocked方法:
```java
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
long startTime = SystemClock.elapsedRealtime();
if (app.pid > 0 && app.pid != MY_PID) {
checkTime(startTime, "startProcess: removing from pids map");
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid); // 如果已经有了这个进程了移除掉
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
checkTime(startTime, "startProcess: done removing from pids map");
app.setPid(0);
}
if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
"startProcessLocked removing on hold: " + app);
mProcessesOnHold.remove(app);
checkTime(startTime, "startProcess: starting to update cpu stats");
updateCpuStats();
checkTime(startTime, "startProcess: done updating cpu stats");
try {
try {
final int userId = UserHandle.getUserId(app.uid);
AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
int uid = app.uid; // 获取该进程的uid
.......................
app.gids = gids;
app.requiredAbi = requiredAbi;
app.instructionSet = instructionSet;
// the per-user SELinux context must be set
if (TextUtils.isEmpty(app.info.seInfoUser)) {
Slog.wtf(TAG, "SELinux tag not defined",
new IllegalStateException("SELinux tag not defined for "
+ app.info.packageName + " (uid " + app.uid + ")"));
}
final String seInfo = app.info.seInfo
+ (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
// 如果创建进程的入口类为null,这里替换为android.app.ActivityThread
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
ProcessStartResult startResult;
if (hostingType.equals("webview_service")) {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, entryPointArgs);
} else {
// 到这里就开始创建一个新进程了,这个启动的类就是android.app.ActivityThread
// 启动后会执行main方法
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);
}
.................
checkTime(startTime, "startProcess: building log message");
StringBuilder buf = mStringBuilder;
buf.setLength(0);
buf.append("Start proc ");
buf.append(startResult.pid);
buf.append(':');
buf.append(app.processName);
buf.append('/');
UserHandle.formatUid(buf, uid);
if (!isActivityProcess) {
buf.append(" [");
buf.append(entryPoint);
buf.append("]");
}
buf.append(" for ");
buf.append(hostingType);
if (hostingNameStr != null) {
buf.append(" ");
buf.append(hostingNameStr);
}
Slog.i(TAG, buf.toString());
app.setPid(startResult.pid);
app.usingWrapper = startResult.usingWrapper;
app.removed = false;
app.killed = false;
app.killedByAm = false;
checkTime(startTime, "startProcess: starting to update pids map");
ProcessRecord oldApp;
synchronized (mPidsSelfLocked) {
// 看看集合中是否已经有这个pid的对象了
oldApp = mPidsSelfLocked.get(startResult.pid);
}
// If there is already an app occupying that pid that hasn't been cleaned up
if (oldApp != null && !app.isolated) {
// Clean up anything relating to this pid first
Slog.w(TAG, "Reusing pid " + startResult.pid
+ " while app is still mapped to it");
// 如果集合中已经有了这个集合的对象,清除掉
cleanUpApplicationRecordLocked(oldApp, false, false, -1,
true /*replacingPid*/);
}
synchronized (mPidsSelfLocked) {
// 把这个进程加入集合
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
checkTime(startTime, "startProcess: done updating pids map");
} catch (RuntimeException e) {
Slog.e(TAG, "Failure starting process " + app.processName, e);
// Something went very wrong while trying to start this process; one
// common case is when the package is frozen due to an active
// upgrade. To recover, clean up any active bookkeeping related to
// starting this process. (We already invoked this method once when
// the package was initially frozen through KILL_APPLICATION_MSG, so
// it doesn't hurt to use it again.)
forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,
false, true, false, false, UserHandle.getUserId(app.userId), "start failure");
}
}
```
这个方法就是创建进程的方法了。首先还是进行校验,在AMS的mPidsSelfLocked这个map中,包含了所有当前正在运行的进程,key是pid,value是ProcessRecord,这里会先检查下,是否已经存在,如果存在就先移除。之后做一些权限检查之类的这个就不多说。然后就开始创建进程了,这里可以看到entryPoint这个变量,如果这个变量为null,一般情况都是null,那么会把他设置为android.app.ActivityThread,这个就是进程的类了,然后回通过Process.start方法来启动一个进程。这个会通过zygote进程来fork一份进程的副本来返回,我们知道除了系统的一些进程外,后续所有的进程都是通过zygote的fork来创建的,这个我们这个不细说,在系统启动的文章里面会在详细分析下一个进程启动的过程,这里只要知道通过Process.start会创建一个新进程返回,返回是一个ProcessStartResult类型的对象,这个对象里面有这个进程的pid。最后把这个进程的pid作为key存入前面说的mPidsSelfLocked对象就可以了。
进程启动后,就会走到android.app.ActivityThread的main方法中去执行,在那里初始化完成后还会通知AMS,AMS收到通知后,在继续创建Activty,这样就和之前存在进程时候的流程就一样了。关键之后进程中的初始化我们下一篇文章再说,这篇文章也已经不少内容了,我们画个时序图来小结下。

这里的时序图主要是从AMS到创建一个进程,至于Activty的各个生命周期的调用由于后面还会讲,所在在那里讲完后再看时序图。
AMS源码分析(三)