Activity/应用(O/8.0)启动流程(一)
Activity/应用(O/8.0)启动流程(二)
Activity/应用(O/8.0)启动流程(三)
Activity/应用(O/8.0)启动流程(四)
上一篇主要是为需要被启动的Activity设置栈信息,要么新建,要么复用。
而遗留的小问题是栈的具体查找赋值,我们现在来具体说一下
setTaskFromReuseOrCreateNewTask 复用栈或者新建栈
setTaskFromSourceRecord 使用执行启动Activity所在的栈
setTaskFromInTask 使用在执行启动时,具体指定的栈
setTaskToCurrentTopOrCreateNewTask 注释说永远也不会发生,而且我也没有看懂什么意思,这里就不再多说了
我们主要来看setTaskFromReuseOrCreateNewTask ,因为下面的那种方式都是复用的,并不涉及创建,这里就不再说了
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 那么就通过ActivityStack创建一个,并保存到ActivityStack中
final TaskRecord task = mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
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 {
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);
}
// 将ActivityStack移动到前台
if (mDoResume) {
mTargetStack.moveToFront("reuseOrNewTask");
}
return START_SUCCESS;
}
我们主要来看两个地方,一个是获取ActivityStack一个是创建TaskRecord
// 获取ActivityStack
private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
int launchFlags, ActivityOptions aOptions) {
// 首先获取启动栈ActivityStack,
// 如果ActivityStack不为空,则直接返回
final TaskRecord task = r.getTask();
ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
if (stack != null) {
return stack;
}
// 如果启动栈里面没有对应的ActivityStack,然后判断将要启动的Activity对应的任务栈所在的ActivityStack,如果不为空则直接返回
final ActivityStack currentStack = task != null ? task.getStack() : null;
if (currentStack != null) {
if (mSupervisor.mFocusedStack != currentStack) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Setting " + "focused stack to r=" + r
+ " task=" + task);
} else {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Focused stack already="
+ mSupervisor.mFocusedStack);
}
return currentStack;
}
if (canLaunchIntoFocusedStack(r, newTask)) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
return mSupervisor.mFocusedStack;
}
if (mSourceDisplayId != DEFAULT_DISPLAY) {
// Try to put the activity in a stack on a secondary display.
stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
if (stack == null) {
// If source display is not suitable - look for topmost valid stack in the system.
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Can't launch on mSourceDisplayId=" + mSourceDisplayId
+ ", looking on all displays.");
stack = mSupervisor.getNextValidLaunchStackLocked(r, mSourceDisplayId);
}
}
// 如果最终我们还是没有获取到ActivityStack,那么我们就要遍历当前屏幕下的所有ActivityStack
if (stack == null) {
// We first try to put the task in the first dynamic stack on home display.
final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
stack = homeDisplayStacks.get(stackNdx);
// 如果是动态创建的栈,则直接返回(getLanucher中会说几种ActivityStack的类型,除了普通应用使用的ActivityStack,其他的都是静态栈)
if (isDynamicStack(stack.mStackId)) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Setting focused stack=" + stack);
return stack;
}
}
// If there is no suitable dynamic stack then we figure out which static stack to use.
final int stackId = task != null ? task.getLaunchStackId() :
bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
FULLSCREEN_WORKSPACE_STACK_ID;
// 如果最终我们还是没有拿到,则通过ActivityStackSupervisor动态创建一个ActivityStack,并保存下来
stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
+ r + " stackId=" + stack.mStackId);
return stack;
}
private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
ActivityOptions aOptions) {
// We are reusing a task, keep the stack!
// 如果复用的任务栈不为空,则直接返回该任务栈所对应的ActivityStack
if (mReuseTask != null) {
return mReuseTask.getStack();
}
// If the activity is of a specific type, return the associated stack, creating it if
// necessary
// ActivityStack的种类分为四种
// APPLICATION_ACTIVITY_TYPE 普通应用类型
// HOME_ACTIVITY_TYPE 桌面应用类型
// RECENTS_ACTIVITY_TYPE 显示最近任务应用类型(我们按下菜单键的时候,会出现一个最近任务列表,这个就是界面就是RecentsActivity)
// ASSISTANT_ACTIVITY_TYPE 这个我就不怎么清楚了 不过找到了一个
// VoiceInteractionManagerService和VoiceInteractionSession脑袋大了不少,这里就暂时不分析了
// 下面的几个判断就是根据要启动的Activity类型 获取相对应的ActivityStack
if (r.isHomeActivity()) {
return mSupervisor.mHomeStack;
}
if (r.isRecentsActivity()) {
return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
if (r.isAssistantActivity()) {
return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
final int launchDisplayId =
(aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
final int launchStackId =
(aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
throw new IllegalArgumentException(
"Stack and display id can't be set at the same time.");
}
if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
}
if (launchStackId == DOCKED_STACK_ID) {
// The preferred launch stack is the docked stack, but it isn't a valid launch stack
// for this activity, so we put the activity in the fullscreen stack.
return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
if (launchDisplayId != INVALID_DISPLAY) {
// Stack id has higher priority than display id.
return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
}
// If we are using Vr2d display, find the virtual display stack.
if (mUsingVr2dDisplay) {
ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
if (DEBUG_STACK) {
Slog.v(TAG, "Launch stack for app: " + r.toString() +
", on virtual display stack:" + as.toString());
}
return as;
}
if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
|| mSourceDisplayId != DEFAULT_DISPLAY) {
return null;
}
// Otherwise handle adjacent launch.
// The parent activity doesn't want to launch the activity on top of itself, but
// instead tries to put it onto other side in side-by-side mode.
// 这里获取一个ActivityStack对象,要么是任务栈所对应的ActivityStack,要么是当前前台的ActivityStack
final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
// 如果是任务栈所对应的ActivityStack则直接返回
if (parentStack != mSupervisor.mFocusedStack) {
// If task's parent stack is not focused - use it during adjacent launch.
return parentStack;
} else {
// 如果位于前台的ActivityStack不为空,并且该ActivityStack的顶部的任务栈等于要启动的Activity所对应的任务栈,则直接返回前台栈
if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
// If task is already on top of focused stack - use it. We don't want to move the
// existing focused task to adjacent stack, just deliver new intent in this case.
return mSupervisor.mFocusedStack;
}
// 下面的是分屏的,这里就不再分析(因为我也看不懂啊。)
if (parentStack != null && parentStack.isDockedStack()) {
// If parent was in docked stack, the natural place to launch another activity
// will be fullscreen, so it can appear alongside the docked window.
return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
ON_TOP);
} else {
// If the parent is not in the docked stack, we check if there is docked window
// and if yes, we will launch into that stack. If not, we just put the new
// activity into parent's stack, because we can't find a better place.
final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
if (dockedStack != null
&& dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) {
// There is a docked stack, but it isn't visible, so we can't launch into that.
return null;
} else {
return dockedStack;
}
}
}
}
上面简单说了ActivityStack创建过程,下面简单说一下TaskRecord的创建过程
// ActivityStack#createTaskRecord
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
addTask(task, toTop, "createTaskRecord");
final boolean isLockscreenShown = mService.mStackSupervisor.mKeyguardController
.isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
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;
}
ok,栈的创建就完结啦,下面也是接着上一篇的说
1)在栈信息配置完之后,我们会继续进行我们的启动工作,下面要说的就是将我们执行启动的Activity进行暂停操作,
// ActivityStackSupervisor#resumeFocusedStackTopActivityLocked
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!readyToResume()) {
return false;
}
// 目标栈不为空 , 并且刚刚也把此栈移动到了前台 所以 会进入这个判断体
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
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;
}
ActivityStack#resumeTopActivityUncheckedLocked -> resumeTopActivityInnerLocked
ActivityStack#resumeTopActivityInnerLocked: 这个类有点绕,因为会调用两次,此时是第一次,只看第一次的标识即可,第二次要进入的时候会再次提醒,没有标识的代表通用:
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
// 首先确认下入参
// 第一次 prev为即将要启动的Activity
// 第二次 prev执行启动的Activity 已暂停的Activity 可以理解为上一个Activity
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.
// 在此栈中找到可以获取焦点的Activity,也就是我们即将要启动的activity
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
final boolean hasRunningActivity = next != null;
// TODO: Maybe this entire condition can get removed?
if (hasRunningActivity && getDisplay() == null) {
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.
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
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.
// 如果没有其他的RESUMED状态的activity,则进入判断体,allResumedActivitiesComplete判断是否还有RESUMED状态的Activity,如果有则返回false
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.
// 如果所有的Activity都进入了pause状态 这就是我们想要的状态 就会进入判断体
// allPausedActivitiesComplete判断所有的Activity是否进入了pause/STOP/STOPPING ,也就是判断是否还有RESUME状态的Activity,
//上一个执行启动操作的activity还是resume状态的,虽然将要启动的activity所对应的栈已经被移动到了前台,所以这里也不会进入判断体
if (shouldSleepOrShutDownActivities()
&& 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.
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.
mStackSupervisor.mStoppingActivities.remove(next);
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
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.
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;
}
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
boolean lastResumedCanPip = false;
final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
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.
final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity;
lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
"resumeTopActivity", 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.
// 这个标识我不太懂,但是因为目前还有RESUMED状态的Activity,所以可以暂时理解为lastResumedCanPip == true,resumeWhilePausing == false,最后再下面的判断整体返回
final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
&& !lastResumedCanPip;
// 第一次 此处判断是否有需要执行pause状态的Activity,上面我们说了 执行启动的Activity目前还是RESUME状态,所以这里会返回true
// 第二次 next代表我们将要启动的Activity,不需要进行暂停操作,返回false
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, false);
}
// ok 第一次执行到这里就结束了 下面继续要走的都是第二次 不在区分
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()) {
// 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.
if (shouldSleepActivities() && mLastNoHistoryActivity != null &&
!mLastNoHistoryActivity.finishing) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"no-history finish of " + mLastNoHistoryActivity + " on new resume");
requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
null, "resume-no-history", false);
mLastNoHistoryActivity = null;
}
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.
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();
}
// 获取当前有焦点的栈,也就是我们将要启动的Activity所在的栈
ActivityStack lastStack = mStackSupervisor.getLastStack();
// next代表我们将要启动的Activity,但是还没有分配进程以及线程 所以下面的不会进入(如果复用了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));
// The contained logic must be synchronized, since we are both changing the visibility
// and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will
// ultimately cause the client code to schedule a layout. Since layouts retrieve the
// current {@link Configuration}, we must ensure that the below code updates it before
// the layout can occur.
synchronized(mWindowManager.getWindowManagerLock()) {
// 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();
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)");
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)) {
// We have special rotation behavior when Keyguard is locked. Make sure all
// activity visibilities are set correctly as well as the transition is updated
// if needed to get the correct rotation behavior.
// TODO: Remove this once visibilities are set correctly immediately when
// starting an activity.
if (mStackSupervisor.mKeyguardController.isKeyguardLocked()) {
mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */,
0 /* configChanges */, false /* preserveWindows */);
}
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);
}
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.
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!
mStackSupervisor.scheduleResumeTopActivities();
}
if (!next.visible || next.stopped) {
next.setVisibility(true);
}
next.completeResumeLocked();
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
try {
// Deliver all pending results.
ArrayList<ResultInfo> a = next.results;
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);
}
}
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();
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有点长,上面说了因为没有分配进程与线程 所以下面就是分配进程与线程的操作
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);
// 主要是这里 入参为我们将要启动的Activity 以及两个true标识
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
上面的代码看了极度不适,我们先来看pauseBackStacks这个方法;总的来说,就是把执行启动的Activity的状态设置为暂停状态,第一次进入上面的方法,在判断还有RESUMED状态的Activity的时候,会执行pauseBackStacks这个方法将RESUMED状态的Activity设置为PAUSE状态
// ActivityStackSupervisor#pauseBackStacks
boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
boolean someActivityPaused = false;
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 (!isFocusedStack(stack) && stack.mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + stack.mResumedActivity);
someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
dontWait);
}
}
}
return someActivityPaused;
}
这个方法是遍历所有的栈,找到RESUME状态的Activity,然后执行startPausingLocked
userLeaving
true 在ActivityStarter#startActivityUnchecked -> setInitialState中进行初始化的
resuming
当前将要启动的Activity
dontWait
false
// ActivityStack#startPausingLocked
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean pauseImmediately) {
if (mPausingActivity != null) {
Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+ " state=" + mPausingActivity.state);
if (!shouldSleepActivities()) {
// Avoid recursion among check for sleep and complete pause during sleeping.
// Because activity will be paused immediately after resume, just let pause
// be completed by the order of activity paused from clients.
completePauseLocked(false, resuming);
}
}
// 当前处于RESUMED状态的Activity,也就是执行启动Activity操作的Activity
ActivityRecord prev = mResumedActivity;
// 如果没有RESUMED状态的Activity直接返回
if (prev == null) {
if (resuming == null) {
Slog.wtf(TAG, "Trying to pause when nothing is resumed");
// 如果既没有RESUMED状态的Activity并且被启动的Activity也为null的话,调用resumeFocusedStackTopActivityLocked,
// 也就是上面我们看了为超级恶心的那个方法,我们也是从那个方法进行了判断才来到这里来进行暂停操作的
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
return false;
}
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
mResumedActivity = null;
mPausingActivity = prev;
mLastPausedActivity = 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;
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();
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;
}
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
mStackSupervisor.acquireLaunchWakelock();
}
// mPausingActivity 就是我们要暂停的Activity
if (mPausingActivity != null) {
// Have the window manager pause its key dispatching until the new
// activity has started. If we're pausing the activity just because
// the screen is being turned off and the UI is sleeping, don't interrupt
// key dispatch; the same activity will pick it up again on wakeup.
if (!uiSleeping) {
prev.pauseKeyDispatchingLocked();
} else if (DEBUG_PAUSE) {
Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
}
//pauseImmediately 就是上面我们说的dowait 如果 为true 就是不等待 回进入判断体
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 {
// 这里会发送一个暂停的延时消息 最后也是会调用completePauseLocked的
// 主要是在Activity暂停之后,通知AMS进行下一步的操作
schedulePauseTimeout(prev);
return true;
}
} else {
// This activity failed to schedule the
// pause, so just treat it as being paused now.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
if (resuming == null) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
return false;
}
}
这里我们会通过ActivityThread去调用我们上一个Activity的onPause方法,并把状态设置为暂停状态
ActivityThread#schedulePauseActivity -> 发送一个PAUSE_ACTIVITY消息 -> handlePauseActivity()-> performPauseActivity&AMS#activityPaused();
我们先来看ActivityThread#performPauseActivity的流程:
ActivityThread#performPauseActivity
final Bundle performPauseActivity(IBinder token, boolean finished,
boolean saveState, String reason) {
// 当我们创建了一个新的Activity时,就会创建一个与之对应的ActivityClientRecord 并保存在mActivities中,具体的时间就是在调用Acitivty之后,
// 可参考ActivityThread#performLaunchActivity()
ActivityClientRecord r = mActivities.get(token);
return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
}
// ActivityThread#performPauseActivity
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
boolean saveState, String reason) {
if (r.paused) {
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain cases.
// So here we likewise don't want to call onPause() if the activity
// isn't resumed.
return null;
}
RuntimeException e = new RuntimeException(
"Performing pause of activity that is not resumed: "
+ r.intent.getComponent().toShortString());
Slog.e(TAG, e.getMessage(), e);
}
if (finished) {
r.activity.mFinished = true;
}
// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
callCallActivityOnSaveInstanceState(r);
}
// 直接看这里
performPauseActivityIfNeeded(r, reason);
// Notify any outstanding on paused listeners
ArrayList<OnActivityPausedListener> listeners;
synchronized (mOnPauseListeners) {
listeners = mOnPauseListeners.remove(r.activity);
}
int size = (listeners != null ? listeners.size() : 0);
for (int i = 0; i < size; i++) {
listeners.get(i).onPaused(r.activity);
}
return !r.activity.mFinished && saveState ? r.state : null;
}
// ActivityThread#performPauseActivityIfNeeded
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
if (r.paused) {
// You are already paused silly...
// 如果该Acitivty已经处于暂停了 那就直接返回
return;
}
try {
r.activity.mCalled = false;
// 这里会调用Activity的onPause方法
mInstrumentation.callActivityOnPause(r.activity);
EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
r.activity.getComponentName().getClassName(), reason);
if (!r.activity.mCalled) {
throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
+ " did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException("Unable to pause activity "
+ safeToComponentShortString(r.intent) + ": " + e.toString(), e);
}
}
// 设置对应的ActivityClientRecord的状态为暂停状态
r.paused = true;
}
// Instrumentation#callActivityOnPause()
public void callActivityOnPause(Activity activity) {
// 到这里 执行启动的Activity算是进入了暂停状态
activity.performPause();
}
2)新进程的分配
上面就是Activity暂停的状态流程,我们继续来看下一个流程,我们在ActivityStack#startPausingLocked执行了上面的暂停操作之后,之后会通过AMS去启动新的Activity
// AMS#activityPaused
@Override
public final void activityPaused(IBinder token) {
final long origId = Binder.clearCallingIdentity();
synchronized(this) {
// 先找到该Activity对应的栈
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
// 通过栈将该Activity的状态修改为暂停状态,(与其说该Acitivty,不如说是ActivityRecord,到这里我们发现,
// 我们先是将ActivityClientRecord设置为暂停状态,然后再将ActivityRecord设置为暂停状态,因为这两个都代表着一个Activity,
// 所以需要同时设置为暂停状态)
stack.activityPausedLocked(token, false);
}
}
Binder.restoreCallingIdentity(origId);
}
ActivityStack#activityPausedLocked
final void activityPausedLocked(IBinder token, boolean timeout) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
"Activity paused: token=" + token + ", timeout=" + timeout);
final ActivityRecord r = isInStackLocked(token);
if (r != null) {
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
if (mPausingActivity == r) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
+ (timeout ? " (due to timeout)" : " (pause complete)"));
mService.mWindowManager.deferSurfaceLayout();
try {
// 主要看这里 入参为true和null
completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
} finally {
mService.mWindowManager.continueSurfaceLayout();
}
return;
} else {
EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
r.userId, System.identityHashCode(r), r.shortComponentName,
mPausingActivity != null
? mPausingActivity.shortComponentName : "(none)");
if (r.state == ActivityState.PAUSING) {
r.state = ActivityState.PAUSED;
if (r.finishing) {
if (DEBUG_PAUSE) Slog.v(TAG,
"Executing finish of failed to pause activity: " + r);
finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false);
}
}
}
}
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
ActivityStack#completePauseLocked
private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
// 首先获取暂停的Activity,也就是我们执行启动的Activity
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) {
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);
}
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 || shouldSleepOrShutDownActivities()) {
// Clear out any deferred client hide we might currently have.
prev.setDeferHidingClient(false);
// If we were visible then resumeTopActivities will release resources before
// stopping.
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*/);
}
// 将被暂停的Activity设置为null
mPausingActivity = null;
}
// 入参为true 上面说过的
if (resumeNext) {
// 获取当前有焦点的栈,也就是我们需要被启动的Activity所在栈
final ActivityStack topStack = mStackSupervisor.getFocusedStack();
if (!topStack.shouldSleepOrShutDownActivities()) {
// 如果当前不是锁屏/关机状态 则会进入这个方法 这个方法在上面说过了,不过两次不一样,代码就不在贴了,
// 方法有点长,上面也已经加了标识 最终会调用ActivityStackSupervisor#startSpecificActivityLocked创建进程
mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
} else {
checkReadyForSleep();
ActivityRecord top = topStack.topRunningActivityLocked();
if (top == null || (prev != null && top != prev)) {
// If there are no more activities available to run, do resume anyway to start
// something. Also if the top activity on the stack is not the just paused
// activity, we need to go ahead and resume it to ensure we complete an
// in-flight app switch.
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
}
}
if (prev != null) {
prev.resumeKeyDispatchingLocked();
if (prev.app != null && prev.cpuTimeAtResume > 0
&& mService.mBatteryStatsService.isOnBattery()) {
long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
- prev.cpuTimeAtResume;
if (diff > 0) {
BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
synchronized (bsi) {
BatteryStatsImpl.Uid.Proc ps =
bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
prev.info.packageName);
if (ps != null) {
ps.addForegroundTimeLocked(diff);
}
}
}
}
prev.cpuTimeAtResume = 0; // reset it
}
// Notify when the task stack has changed, but only if visibilities changed (not just
// focus). Also if there is an active pinned stack - we always want to notify it about
// task stack changes, because its positioning may depend on it.
if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause
|| mService.mStackSupervisor.getStack(PINNED_STACK_ID) != null) {
mService.mTaskChangeNotificationController.notifyTaskStackChanged();
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
}
mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS);
}
ActivityStackSupervisor#startSpecificActivityLocked:
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
// 先通过AMS根据进程名与uid判断是否存在相应的进程
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 直接去启动 这里先留下,我们走不存在的情况
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.
}
// 如果不存在 就需要去创建进程了
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}