// frameworks/base/services/core/java/com/android/server/am/ActivityStarter.javaprivateintstartActivity(......){int result = START_CANCELED;try{
mService.mWindowManager.deferSurfaceLayout();// 转调用
result =startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);}finally{// If we are not able to proceed, disassociate the activity from the task. Leaving an// activity in an incomplete state can lead to issues, such as performing operations// without a window container.final ActivityStack stack = mStartActivity.getStack();if(!ActivityManager.isStartResultSuccessful(result)&& stack != null){
stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
null /* intentResultData */,"startActivity",true/* oomAdj */);}
mService.mWindowManager.continueSurfaceLayout();}postStartActivityProcessing(r, result, mTargetStack);return result;}----------------------------------------------------------------------------------------------------------------------------------------------------------privateintstartActivityUnchecked(......){//根据参数重新设置ActivityStarter的成员变量setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,voiceInteractor);// 计算mLaunchFlags, 一般是判断是否需要在mLaunchFlags中加入FLAG_ACTIVITY_NEW_TASKcomputeLaunchingTaskFlags()// 获得mSourceStackcomputeSourceStack();
mIntent.setFlags(mLaunchFlags);// 判断新Activity是否可以复用之前已经启动的Activity,返回null表示否,一般指定了TaskId的情况下才会出现复用
ActivityRecord reusedActivity =getReusableIntentActivity();....if(reusedActivity != null){// 处理Activity复用的情况// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but// still needs to be a lock task mode violation since the task gets cleared out and// the device would otherwise leave the locked task....// 设置待启动Activity的Task// If mStartActivity does not have a task associated with it, associate it with the// reused activity's task. Do not do so if we're clearing top and resetting for a// standard launchMode activity.if(mStartActivity.getTask()== null &&!clearTopAndResetStandardLaunchMode){
mStartActivity.setTask(reusedActivity.getTask());}if(reusedActivity.getTask().intent == null){// 如果复用Activity之前的Task没有Intent,现在重新设置// This task was started because of movement of the activity based on affinity...// Now that we are actually launching it, we can assign the base intent.
reusedActivity.getTask().setIntent(mStartActivity);}// 以singleTask等方式启动现有Task中的Activity,将会清空该Activity其上的Activity// This code path leads to delivering a new intent, we want to make sure we schedule it// as the first operation, in case the activity will be resumed as a result of later// operations.if((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP)!=0||isDocumentLaunchesIntoExisting(mLaunchFlags)||isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)){final TaskRecord task = reusedActivity.getTask();// 这里进行清空操作// In this situation we want to remove all activities from the task up to the one// being started. In most cases this means we are resetting the task to its initial// state.final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
mLaunchFlags);// The above code can remove {@code reusedActivity} from the task, leading to the// the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The// task reference is needed in the call below to// {@link setTargetStackAndMoveToFrontIfNeeded}.if(reusedActivity.getTask()== null){
reusedActivity.setTask(task);}if(top != null){if(top.frontOfTask){// 设置top activity为待启动的Activity// Activity aliases may mean we use different intents for the top activity,// so make sure the task now has the identity of the new intent.
top.getTask().setIntent(mStartActivity);}// 回调待启动Activity的onNewIntent方法deliverNewIntent(top);}}
mSupervisor.sendPowerHintForLaunchStartIfNeeded(false/* forceSend */, reusedActivity);// 将复用Activity对应的TaskRecord插入到相应的ActivityStack的顶部,并将该ActivityStack移动到前台
reusedActivity =setTargetStackAndMoveToFrontIfNeeded(reusedActivity);final ActivityRecord outResult =
outActivity != null && outActivity.length >0? outActivity[0]: null;// 处理返回结果// When there is a reused activity and the current result is a trampoline activity,// set the reused activity as the result.if(outResult != null &&(outResult.finishing || outResult.noDisplay)){
outActivity[0]= reusedActivity;}if((mStartFlags & START_FLAG_ONLY_IF_NEEDED)!=0){// 该函数会调用到ActivityStackSupervisor的resumeFocusedStackTopActivityLocked函数后面会有介绍// 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! And for paranoia, make sure we have// correctly resumed the top activity.resumeTargetStackIfNeeded();return START_RETURN_INTENT_TO_CALLER;}if(reusedActivity != null){// 据复用Activity的信息,修改待加入Task相关的变量setTaskFromIntentActivity(reusedActivity);if(!mAddingToTask && mReuseTask == null){// We didn't do anything... but it was needed (a.k.a., client don't use that// intent!) And for paranoia, make sure we have correctly resumed the top activity.resumeTargetStackIfNeeded();if(outActivity != null && outActivity.length >0){
outActivity[0]= reusedActivity;}return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;}}}....// 下面的代码会配置Activity的Task和Stack,后面详细分析// Should this be considered a new task?int result = START_SUCCESS;if(mStartActivity.resultTo == null && mInTask == null &&!mAddingToTask
&&(mLaunchFlags & FLAG_ACTIVITY_NEW_TASK)!=0){
newTask =true;
result =setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack); 【1】
}elseif(mSourceRecord != null){
result =setTaskFromSourceRecord();}elseif(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.setTaskToCurrentTopOrCreateNewTask();}if(result != START_SUCCESS){return result;}....// 通知WindowManager准备App切换相关的工作
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);if(mDoResume){final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();if(!mTargetStack.isFocusable()||(topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)){// If the activity is not focusable, we can't resume it, but still would like to// make sure it becomes visible as it starts (this will also trigger entry// animation). An example of this are PIP activities.// Also, we don't want to resume activities in a task that currently has an overlay// as the starting activity just needs to be in the visible paused state until the// over is removed.
mTargetStack.ensureActivitiesVisibleLocked(null,0,!PRESERVE_WINDOWS);// Go ahead and tell window manager to execute app transition for this activity// since the app transition will not be triggered through the resume channel.
mService.mWindowManager.executeAppTransition();}else{// If the target stack was not previously focusable (previous top running activity// on that stack was not visible) then any prior calls to move the stack to the// will not update the focused stack. If starting the new activity now allows the// task stack to be focusable, then ensure that we now update the focused stack// accordingly.if(mTargetStack.isFocusable()&&!mSupervisor.isFocusedStack(mTargetStack)){
mTargetStack.moveToFront("startActivityUnchecked");}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions); 【2】
}}elseif(mStartActivity != null){
mSupervisor.mRecentTasks.add(mStartActivity.getTask());}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
preferredLaunchDisplayId, mTargetStack);return START_SUCCESS;}
// frameworks/base/services/core/java/com/android/server/am/ActivityStarter.javaprivate ActivityStack getLaunchStack(ActivityRecord r,int launchFlags, TaskRecord task,
ActivityOptions aOptions){// TaskRecord重用的情况这里不考虑// We are reusing a task, keep the stack!if(mReuseTask != null){return mReuseTask.getStack();}if(((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT)==0)|| mPreferredDisplayId != DEFAULT_DISPLAY){// We don't pass in the default display id into the get launch stack call so it can do a// full resolution.finalint candidateDisplay =
mPreferredDisplayId != DEFAULT_DISPLAY ? mPreferredDisplayId : INVALID_DISPLAY;return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP, candidateDisplay);}// 后面处理包含FLAG_ACTIVITY_LAUNCH_ADJACENT的情况....}
这里调用了ActivityStackSupervisor的getLaunchStack函数
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java<T extendsActivityStack> T getLaunchStack(@Nullable ActivityRecord r,@Nullable ActivityOptions options,@Nullable TaskRecord candidateTask,boolean onTop,int candidateDisplayId){int taskId = INVALID_TASK_ID;int displayId = INVALID_DISPLAY;//Rect bounds = null;// 从ActivityOptions中获取taskId和displayId,ActivityOptions可以在启动App的时候指定// We give preference to the launch preference in activity options.if(options != null){
taskId = options.getLaunchTaskId();
displayId = options.getLaunchDisplayId();// TODO: Need to work this into the equation...//bounds = options.getLaunchBounds();}// First preference for stack goes to the task Id set in the activity options. Use the stack// associated with that if possible.if(taskId != INVALID_TASK_ID){// Temporarily set the task id to invalid in case in re-entry.
options.setLaunchTaskId(INVALID_TASK_ID);final TaskRecord task =anyTaskForIdLocked(taskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options, onTop);
options.setLaunchTaskId(taskId);if(task != null){return task.getStack();}}finalint activityType =resolveActivityType(r, options, candidateTask);
T stack = null;// Next preference for stack goes to the display Id set in the activity options or the// candidate display.if(displayId == INVALID_DISPLAY){
displayId = candidateDisplayId;}if(displayId != INVALID_DISPLAY &&canLaunchOnDisplay(r, displayId)){if(r != null){// TODO: This should also take in the windowing mode and activity type into account.
stack =(T)getValidLaunchStackOnDisplay(displayId, r);if(stack != null){return stack;}}// 根据displayId获取ActivityDisplay对象final ActivityDisplay display =getActivityDisplayOrCreateLocked(displayId);if(display != null){// 调用ActivityDisplay的getOrCreateStack函数创建ActivityStack
stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop);if(stack != null){return stack;}}}// 后面是无法根据displayId获取对应的ActivityDisplay的情况...}
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.javavoidmoveToFront(String reason, TaskRecord task){if(!isAttached()){return;}// 获取ActivityDisplayfinal ActivityDisplay display =getDisplay();if(inSplitScreenSecondaryWindowingMode()){// 多窗口...}if(!isActivityTypeHome()&&returnsToHomeStack()){// 启动Home// Make sure the home stack is behind this stack since that is where we should return to// when this stack is no longer visible.
mStackSupervisor.moveHomeStackToFront(reason +" returnToHome");}
display.positionChildAtTop(this);// 设置ActivityStackSupervisor的mFocusedStack为当前的Stack
mStackSupervisor.setFocusStackUnchecked(reason,this);if(task != null){insertTaskAtTop(task, null);return;}}
调用display的positionChildAtTop函数
// frameworks/base/services/core/java/com/android/server/am/ActivityDisplay.javavoidpositionChildAtTop(ActivityStack stack){// 转调用positionChildAt(stack, mStacks.size());}----------------------------------------------------------------------------------------------------------------------------------------------------------privatevoidpositionChildAt(ActivityStack stack,int position){// TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust// the position internally, also update the logic here
mStacks.remove(stack);finalint insertPosition =getTopInsertPosition(stack, position);// 将ActiviStack插入到ActivityDisplay的mStacks列表中
mStacks.add(insertPosition, stack);
mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
insertPosition);onStackOrderChanged();}
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.javabooleanresumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions){if(!readyToResume()){returnfalse;}if(targetStack != null &&isFocusedStack(targetStack)){// 转调用return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);}final ActivityRecord r = mFocusedStack.topRunningActivityLocked();if(r == null ||!r.isState(RESUMED)){
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);}elseif(r.isState(RESUMED)){// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);}returnfalse;}----------------------------------------------------------------------------------------------------------------------------------------------------------booleanresumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options){if(mStackSupervisor.inResumeTopActivity){// Don't even start recursing.returnfalse;}boolean result =false;try{// Protect against recursion.
mStackSupervisor.inResumeTopActivity =true;// 转调用
result =resumeTopActivityInnerLocked(prev, options);// When resuming the top activity, it may be necessary to pause the top activity (for// example, returning to the lock screen. We suppress the normal pause logic in// {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the// end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here// to ensure any necessary pause logic occurs. In the case where the Activity will be// shown regardless of the lock screen, the call to// {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.final ActivityRecord next =topRunningActivityLocked(true/* focusableOnly */);if(next == null ||!next.canTurnScreenOn()){checkReadyForSleep();}}finally{
mStackSupervisor.inResumeTopActivity =false;}return result;}----------------------------------------------------------------------------------------------------------------------------------------------------------privatebooleanresumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options){if(!mService.mBooting &&!mService.mBooted){// Not ready yet!returnfalse;}// 获取TaskRecord的栈顶Activity,如果正常的话这个ActivityRecord为待启动的Activity // 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.final ActivityRecord next =topRunningActivityLocked(true/* focusableOnly */);finalboolean hasRunningActivity = next != null;...// 将待启动的Activity从下面几个队列中移除// 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);// 如果系统当前正在中断一个Activity,需要先等待那个Activity pause完毕,之后系统会重新调用resumeTopActivityInnerLocked函数,找到下一个要启动的Activity// 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();returnfalse;}...boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next,false);// mResumedActivity指向上一次启动的Activity,也就是当前界面显示的Activityif(mResumedActivity != null){// 如果当前界面显示了一个Activity,那么在启动新的Activity之前// 必须中断当前的Activity,也就是调用当前Activity的onPause函数if(DEBUG_STATES) Slog.d(TAG_STATES,"resumeTopActivityLocked: Pausing "+ mResumedActivity);
pausing |=startPausingLocked(userLeaving,false, next,false);}if(pausing &&!resumeWhilePausing){//如果系统正在中断当前启动的Activity,并且未设置FLAG_RESUME_WHILE_PAUSING标签则会 //进入该分支,等当前Activity中断完成之后会重新调用resumeTopActivityInnerLocked函数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){// 在中断当前界面的Activity时,调整待启动Activity所在进程的优先级,保证其不被kill
mService.updateLruProcessLocked(next.app,true, null);}if(DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();if(lastResumed != null){
lastResumed.setWillCloseOrEnterPip(true);}returntrue;}elseif(mResumedActivity == next && next.isState(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();returntrue;}// 若之前存在未正常结束的Activity,那么要优先结束掉这些Activity// 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;}...
ActivityStack lastStack = mStackSupervisor.getLastStack();if(next.app != null && next.app.thread != null){// 如果待启动的Activity已有对应的进程存在,则只需要重启Activity...}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);//如果待启动的Activity进程不存在则调用ActivityStackSupervisor的startSpecificActivityLocked函数,启动整个进程
mStackSupervisor.startSpecificActivityLocked(next,true,true);}if(DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();returntrue;}
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.javavoidstartSpecificActivityLocked(ActivityRecord r,boolean andResume,boolean checkConfig){// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid,true);getLaunchTimeTracker().setLaunchTime(r);//如果对应进程已经存在,并向AMS注册过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.longVersionCode,
mService.mProcessStats);}//通知进程启动目标Activity,该函数在第二篇文章中分析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.}// 调用ActivityManagerService的startProcessLocked函数
mService.startProcessLocked(r.processName, r.info.applicationInfo,true,0,"activity", r.intent.getComponent(),false,false,true);}
顺着流程,接下来看AMS的startProcessLocked函数:
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info,boolean knownToBeDead,int intentFlags,
String hostingType, ComponentName hostingName,boolean allowWhileBooting,boolean isolated,boolean keepIfLarge){// 转调用returnstartProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated,0/* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);}----------------------------------------------------------------------------------------------------------------------------------------------------------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用来记录进程信息
ProcessRecord app;if(!isolated){// 根据processName和uid寻找是否已经存在processRecord
app =getProcessRecordLocked(processName, info.uid, keepIfLarge);checkTime(startTime,"startProcess: after getProcessRecord");// FLAG_FROM_BACKGROUND表示发起这次启动的Task属于后台任务// 如果没有设置该标志,那么本次启动请求就是由前台Task触发的if((intentFlags & Intent.FLAG_FROM_BACKGROUND)!=0){//如果一个应用在1分钟内连续崩溃超过两次,AMS就会将其ProcessRecord加入到BadProcesses中 //正常情况下,一个应用崩溃后,系统会弹出一个警告框以提醒用户 //但是如果一个后台Task启动BadProcess,然后该Process崩溃,由于用户看不到该Process对应的界面, //若弹出一个警告框,用户将觉得奇怪;因此,此处禁止后台Task启动BadProcess// 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{//如果用户从界面主动选择启动一个Process,即使该Process是BadProcess,也不能禁止该操作 //而且还要清空对应Process的“不良”记录 //对比上面的代码,可以看出这其实是一种安全机制,防止不健全的程序不断启动潜在的崩溃组件,但该机制不限制用户行为// 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;}...if(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;
app.isolatedEntryPoint = entryPoint;
app.isolatedEntryPointArgs = entryPointArgs;checkTime(startTime,"startProcess: done creating new process record");}else{// 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");}// 如果当前系统没有准备好,则将app信息保存在mProcessesOnHold列表中// 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");// 调用下一个startProcessLocked函数finalboolean success =startProcessLocked(app, hostingType, hostingNameStr, abiOverride);checkTime(startTime,"startProcess: done starting proc!");return success ? app : null;}