本篇文章是基于Android refs/tags/android-9.0.0_r8分支的代码进行分析的 在分析Activity启动的源码之前先介绍一下Activity的一些基本概念。
关于Android中Activity和Task的介绍,个人觉得《深入理解Android》中的例子不错。我们就借鉴其中的例子,进行相应的说明: 上图模拟了用户在Android系统上想干的三件事,分别用A、B、C表示。在Android中,每一件事可以被看作是一个Task;一个Task可以被细分成多个子步骤,每个子步骤可以被看作是一个Activity。
另外A、B两个Task使用了不同的Activity来完成相应的任务,即A、B两个Task的Activity之间没有复用。但是在Task C中,分别使用了Task A中的A1、Task B中的B2。这么设计的原因是:用户想做的事情(Task)即使完全不同,但是当细分Task为Activity时,就可能出现Activity功能类似的情况。当Task A和Task B中已经有能满足需求的Activity时,Task C就会优先复用而不是重新创建Activity。通过重用Activity可以节省一定的开销,同时为用户提供一致的用户界面。
对Android的设计理念有一定的了解后,我们看看Android是如何组织Task及它所包含的Activity的。 上图为一个比较经典的示例:图中的Task包含4个Activity。用户可以单击按钮跳转到下一个Activity。同时,通过返回键可以回到上一个Activity。图中虚线下方为Activity的组织方式。从图中可以看出,Task是以栈的形式管理Activity的,先启动的Activity成位于栈底,后启动的Activity将作为栈顶成员显示在界面上。
了解了Activity和Task的概念之后我们再看看AMS中的ActivityRecord、TaskRecord、ActivityStack和ActivityDisplay
ActivityRecord:在AMS中ActivityRecord是Activity的代表,ActivityRecord中的成员变量TaskRecord task代表当前Activity所在的栈,那么他的栈信息就保存在TaskRecord中。TaskRecord:TaskRecord是Task的代表,TaskRecord其中两个成员变量: ArrayList <ActivityRecord> mActivities:这个就是当前栈中所管理的Activity的列表 ActivityStack mStack:他是ActivityRecord和TaskRecord的管理者ActivityStack:从名字上看,感觉他是真正的栈,但实际上他是一个Manager的角色,他是负责管理协调ActivityRecord和TaskRecord的。ActivityStack中的成员变量ArrayList<TaskRecord> mTaskHistory记录的是当前ActivityStack管理的所有的栈。ActivityDisplay:他是显示屏的抽象,每一个ActivityDisplay代表一块屏幕,在开机过程中AMS会根据DisplayManager的Display信息在AMS中创建ActivityDisplay。 下面是一个简单的关系图可以看到一个ActivityDisplay可以包含多个ActivityStack,ActivityStack也包含很多个TaskRecord,一个TaskRecord又可以包含很多个ActivityRecord。
接下来我们将利用am命令启动一个Activity,来分析Activity的启动流程的源码。
am start -W -n com.android.settings/com.android.settings.Settings-W:表示等待目标activity启动的返回结果 -n :后接component name用于指定启动的Activity
在shell中输入如上命令之后会得到如下返回结果:
generic_x86_64:/ $ am start -W -n com.android.settings/com.android.settings.Settings Starting: Intent { cmp=com.android.settings/.Settings } Status: ok Activity: com.android.settings/.Settings ThisTime: 209 TotalTime: 209 WaitTime: 231 Complete下面讲进入正篇,分析Activity启动的源码
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerShellCommand.java int runStartActivity(PrintWriter pw) throws RemoteException { // 首先通过makeIntent函数解析am命令的参数,然后根据参数生成Internet Intent intent; try { intent = makeIntent(UserHandle.USER_CURRENT); } catch (URISyntaxException e) { throw new RuntimeException(e.getMessage(), e); } ... // 创建并初始化ActivityOptions,ActivityOptions中保存着DisplayId,WindowingMode,ActivityType等信息 ActivityOptions options = null; if (mDisplayId != INVALID_DISPLAY) { options = ActivityOptions.makeBasic(); options.setLaunchDisplayId(mDisplayId); } if (mWindowingMode != WINDOWING_MODE_UNDEFINED) { if (options == null) { options = ActivityOptions.makeBasic(); } options.setLaunchWindowingMode(mWindowingMode); } if (mActivityType != ACTIVITY_TYPE_UNDEFINED) { if (options == null) { options = ActivityOptions.makeBasic(); } options.setLaunchActivityType(mActivityType); } if (mTaskId != INVALID_TASK_ID) { if (options == null) { options = ActivityOptions.makeBasic(); } options.setLaunchTaskId(mTaskId); if (mIsTaskOverlay) { options.setTaskOverlay(true, true /* canResume */); } } if (mIsLockTask) { if (options == null) { options = ActivityOptions.makeBasic(); } options.setLockTaskEnabled(true); } // 由于设置了-W参数,所以这里mWaitOption = true if (mWaitOption) { // mInterface为ActivityManagerService的代理对象,这里调用了AMS的startActivityAndWait函数 result = mInterface.startActivityAndWait(null, null, intent, mimeType, null, null, 0, mStartFlags, profilerInfo, options != null ? options.toBundle() : null, mUserId); res = result.result; } else { res = mInterface.startActivityAsUser(null, null, intent, mimeType, null, null, 0, mStartFlags, profilerInfo, options != null ? options.toBundle() : null, mUserId); } // 处理result ... return 0; }runStartActivity函数首先会解析am命令的参数并创建Intent和ActivityOptions,然后通过Binder调用ActivityManagerService的startActivityAndWait函数
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public final WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) { enforceNotIsolatedCaller("startActivityAndWait"); userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivityAndWait", null); WaitResult res = new WaitResult(); // TODO: Switch to user app stacks here. // mActivityStartController.obtainStarter会返回ActivityStarter对象 mActivityStartController.obtainStarter(intent, "startActivityAndWait") .setCaller(caller) .setCallingPackage(callingPackage) .setResolvedType(resolvedType) .setResultTo(resultTo) .setResultWho(resultWho) .setRequestCode(requestCode) .setStartFlags(startFlags) .setActivityOptions(bOptions) .setMayWait(userId) .setProfilerInfo(profilerInfo) .setWaitResult(res) .execute(); return res; }在startActivityAndWait函数中,首先获取并初始化ActivityStarter对象,然后调用他的execute方法
// frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java int execute() { try { // TODO(b/64750076): Look into passing request directly to these methods to allow // for transactional diffs and preprocessing. if (mRequest.mayWait) { return startActivityMayWait(mRequest.caller, mRequest.callingUid, mRequest.callingPackage, mRequest.intent, mRequest.resolvedType, mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo, mRequest.resultWho, mRequest.requestCode, mRequest.startFlags, mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig, mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId, mRequest.inTask, mRequest.reason, mRequest.allowPendingRemoteAnimationRegistryLookup); } else { return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent, mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo, mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo, mRequest.resultWho, mRequest.requestCode, mRequest.callingPid, mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.componentSpecified, mRequest.outActivity, mRequest.inTask, mRequest.reason, mRequest.allowPendingRemoteAnimationRegistryLookup); } } finally { onExecutionComplete(); } }这里由于使用了-W参数所以这里调用startActivityMayWait方法,前面都是一些转调用,后面才开始真正的处理流程
这里解释下该函数中几个重要参数:
参数说明caller用于跟调用者进程的ApplicationThread进行通信的binder代理类callingUid调用者的uidcallingPackage调用者的包名intent启动Activity时传的参数resultTo根据resultTo可以找到调用者的ActivityRecord,用于接收返回结果startFlagsIntent携带的start activity对应的flagprofilerInfo性能统计有关相关outResult用于保存返回结果globalConfig以特定的配置启动Activity,例如横屏启动Activity时optionsActivityOptions类型,可以指定Activity的WindowingMode,DisplayID等userId用户ID,多用户相关inTask指定启动Activity的Task继续分析启动流程startActivity
// frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java private int startActivity(......) { if (TextUtils.isEmpty(reason)) { throw new IllegalArgumentException("Need to specify a reason."); } mLastStartReason = reason; mLastStartActivityTimeMs = System.currentTimeMillis(); mLastStartActivityRecord[0] = null; // 转调用 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord, inTask, allowPendingRemoteAnimationRegistryLookup); if (outActivity != null) { // mLastStartActivityRecord[0] is set in the call to startActivity above. outActivity[0] = mLastStartActivityRecord[0]; } return getExternalResult(mLastStartActivityResult); } ---------------------------------------------------------------------------------------------------------------------------------------------------------- private int startActivity(......) { int err = ActivityManager.START_SUCCESS; // Pull the optional Ephemeral Installer-only bundle out of the options early. final Bundle verificationBundle = options != null ? options.popAppVerificationBundle() : null; ProcessRecord callerApp = null; if (caller != null) { // 如果参数中的调用者不为空,则从AMS中找到对应的ProcessRecord,目的是得到调用者的pid和uid callerApp = mService.getRecordForAppLocked(caller); if (callerApp != null) { callingPid = callerApp.pid; callingUid = callerApp.info.uid; } else { Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " + intent.toString()); err = ActivityManager.START_PERMISSION_DENIED; } } ... // sourceRecord用于保存父Activity的信息 ActivityRecord sourceRecord = null; // resultRecord用于保存接收启动结果的Activity,对于startActivityForResult才有意义 ActivityRecord resultRecord = null; if (resultTo != null) { // 根据参数resultTo从ActivityStackSupervisor中获取对应的ActivityRecord sourceRecord = mSupervisor.isInAnyStackLocked(resultTo); if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord); if (sourceRecord != null) { if (requestCode >= 0 && !sourceRecord.finishing) { resultRecord = sourceRecord; } } } // 得到启动Activity使用的标志位 final int launchFlags = intent.getFlags(); if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { // 处理launchFlags中包含Intent.FLAG_ACTIVITY_FORWARD_RESULT的情况 ... } // 错误检查,以及权限检查,这里省略 ... // 通过ActivityInfo等信息创建ActivityRecord对象 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor, checkedOptions, sourceRecord); if (outActivity != null) { outActivity[0] = r; } ... if (mService.mDidAppSwitch) { // 检查调用进程是否有权限切换Activity // This is the second allowed switch since we stopped switches, // so now just generally allow switches. Use case: user presses // home (switches disabled, switch to home, mDidAppSwitch now true); // user taps a home icon (coming from home so allowed, we hit here // and now allow anyone to switch again). mService.mAppSwitchesAllowedTime = 0; } else { mService.mDidAppSwitch = true; } // 处理由于不允许切换Activity时而处于Pending状态的Activity mController.doPendingActivityLaunches(false); // 调用startActivity return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask, outActivity); }startActivity函数很长,但主干比较清晰,只是添加许多条件判断。 从代码来看主要工作包括:
处理sourceRecord和resultRecord, sourceRecord表示发起本次请求的Activity,即父Activity对应的信息; resultRecord表示接收处理结果的Activity。 在一般情况下,sourceRecord和resultRecord应指向同一个Activity;创建ActivityRecord,ActivityRecord用于保存Activity的信息,也就是说现在AMS中已经拥有了该Activity的实例,但是该Activity还没有和TaskRecord关联,之后会介绍关联的过程。处理app switch 如果AMS当前禁止app switch,那么AMS会将本次请求保存起来,以待允许app switch时再进行处理。调用startActivity继续进行本次请求startActivityUnchecked函数最重要的工作就是为待启动的ActivityRecord找到他对应的TaskRecord和ActivityStack,接下来重点介绍TaskRecord和ActivityStack的创建和关联过程(以setTaskFromReuseOrCreateNewTask函数为例)由于代码中分支比较多,所以只分析了其中的一条线,其他分支感兴趣的可以自己看看。
// frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java private int setTaskFromReuseOrCreateNewTask( TaskRecord taskToAffiliate, ActivityStack topStack) { // 【1.1】获取ActivityStack mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions); // Do no move the target stack to front yet, as we might bail if // isLockTaskModeViolation fails below. if (mReuseTask == null) { // 【1.2】创建TaskRecord final TaskRecord task = mTargetStack.createTaskRecord( mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info, mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord, mOptions); // 【1.3】将ActivityRecord添加到TaskRecord中 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask"); updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds); 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 (mService.getLockTaskController().isLockTaskModeViolation(mStartActivity.getTask())) { Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); return START_RETURN_LOCK_TASK_MODE_VIOLATION; } if (mDoResume) { // 【1.4】将ActivityStack移动到顶部 mTargetStack.moveToFront("reuseOrNewTask"); } return START_SUCCESS; }接下来一步一步进行分析: 【1.1】获取ActivityStack
// frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, int launchFlags, ActivityOptions aOptions) { // 在不指定inTask的情况下这里的task一般为null final TaskRecord task = r.getTask(); ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions); if (stack != null) { return stack; } // 后面处理ActivityStack创建失败的情况 .... }后面的处理暂时先不管先看getLaunchStack函数
// frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java private 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. final int 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 extends ActivityStack> 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(); } } final int 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的情况 ... }这里根据displayId获取对应的ActivityDisplay对象,ActivityDisplay是屏幕的抽象,用mDisplayId区分不同的屏幕,其中保存着ActivityStack的列表ArrayList<ActivityStack> mStacks,列表中保存的ActivityStack就是需要在这块屏幕上显示的。
// frameworks/base/services/core/java/com/android/server/am/ActivityDisplay.java <T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType, boolean onTop) { if (!alwaysCreateStack(windowingMode, activityType)) { T stack = getStack(windowingMode, activityType); if (stack != null) { return stack; } } return createStack(windowingMode, activityType, onTop); }调用createStack
// frameworks/base/services/core/java/com/android/server/am/ActivityDisplay.java <T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) { // 省略特殊处理 .... // 获取stackId final int stackId = getNextStackId(); return createStackUnchecked(windowingMode, activityType, stackId, onTop); }获得stackId然后调用createStackUnchecked
// frameworks/base/services/core/java/com/android/server/am/ActivityDisplay.java <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop) { if (windowingMode == WINDOWING_MODE_PINNED) { return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop); } return (T) new ActivityStack( this, stackId, mSupervisor, windowingMode, activityType, onTop); }终于找到了ActivityStack创建的位置了,可见ActivityStack是由ActivityDisplay创建的,下面看看ActivityStack的构造函数
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, int windowingMode, int activityType, boolean onTop) { mStackSupervisor = supervisor; mService = supervisor.mService; mHandler = new ActivityStackHandler(mService.mHandler.getLooper()); mWindowManager = mService.mWindowManager; mStackId = stackId; mCurrentUser = mService.mUserController.getCurrentUserId(); mTmpRect2.setEmpty(); // Set display id before setting activity and window type to make sure it won't affect // stacks on a wrong display. mDisplayId = display.mDisplayId; setActivityType(activityType); // 多窗口的windowingMode setWindowingMode(windowingMode); mWindowContainerController = createStackWindowController(display.mDisplayId, onTop, mTmpRect2); // 多屏的处理感兴趣的可以自己看看 postAddToDisplay(display, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop); }目前为止已经创建了ActivityRecord和ActivityStack还差TaskRecord,接下来回到ActivityStarter的setTaskFromReuseOrCreateNewTask函数继续分析TaskRecord的创建过程 【1.2】TaskRecord创建
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity, ActivityRecord source, ActivityOptions options) { // 创建TaskRecord final TaskRecord task = TaskRecord.create( mService, taskId, info, intent, voiceSession, voiceInteractor); // add the task to stack first, mTaskPositioner might need the stack association // 将TaskRecord插入到ActivityStack的mTaskHistory列表中,如果toTop为true则将该TaskRecord放在mTaskHistory的顶部。这样ActivityStack和TaskRecord就关联起来了 addTask(task, toTop, "createTaskRecord"); .... return task; }到这里TaskRecord创建完成,注意这里不单单创建了TaskRecord,还将新建的TaskRecord插入到了ActivityStack中mTaskHistory中,将TaskRecord和ActivityStack关联在了一起。
【1.3】将ActivityRecord添加到TaskRecord中
// frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java private void addOrReparentStartingActivity(TaskRecord parent, String reason) { // parent为上面创建的TaskRecord,这里由于未指定inTask,所以mStartActivity.getTask()返回null if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) { // 调用TaskRecord的addActivityToTop函数讲待启动的Activity插入到TaskRecord中的mActivities的顶部 parent.addActivityToTop(mStartActivity); } else { mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason); } }现在我们已经将ActivityRecord,TaskRecord和ActivityStack创建完成,并且建立了他们之间的关系。 【1.4】将ActivityStack移动到顶部
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java void moveToFront(String reason, TaskRecord task) { if (!isAttached()) { return; } // 获取ActivityDisplay final 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.java void positionChildAtTop(ActivityStack stack) { // 转调用 positionChildAt(stack, mStacks.size()); } ---------------------------------------------------------------------------------------------------------------------------------------------------------- private void positionChildAt(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); final int insertPosition = getTopInsertPosition(stack, position); // 将ActiviStack插入到ActivityDisplay的mStacks列表中 mStacks.add(insertPosition, stack); mWindowContainerController.positionChildAt(stack.getWindowContainerController(), insertPosition); onStackOrderChanged(); }到这里ActivityRecord,TaskRecord,ActivityStack,ActivityDisplay已关联完成,并且ActivityStackSuperVisor中的mTargetStack也更新完成。下面通过一张图片总结一下这个过程
调用ActivityDisplay的getOrCreateStack函数创建ActivityStack调用ActivityStack的createTaskRecord函数创建TaskRecord,并将TaskRecord保存在mTaskHistory中调用ActivityStarter的addOrReparentStartingActivity函数将之前创建的ActivityRecord插入到TaskRecord的顶部调用ActivityStack的moveToFront函数将自己插入到ActicityDisplay中的mStacks的顶部,并修改ActivityStackSuperVisor的mTargetStack变量为当前ActivityStack 最后在AMS中形成上图所示的结构回到ActivityStarter的startActivityUnchecked函数继续分析
【2】ActivityStackSupervisor的resumeFocusedStackTopActivityLocked函数
// frameworks/base/services/core/java/com/android/server/am/ActivityStack.java 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.isState(RESUMED)) { mFocusedStack.resumeTopActivityUncheckedLocked(null, null); } else if (r.isState(RESUMED)) { // Kick off any lingering app transitions form the MoveTaskToFront operation. mFocusedStack.executeAppTransition(targetOptions); } return false; } ---------------------------------------------------------------------------------------------------------------------------------------------------------- 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; // 转调用 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; } ---------------------------------------------------------------------------------------------------------------------------------------------------------- private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { if (!mService.mBooting && !mService.mBooted) { // Not ready yet! return false; } // 获取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 */); final boolean 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(); return false; } ... boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false); // mResumedActivity指向上一次启动的Activity,也就是当前界面显示的Activity if (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); } return true; } else if (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(); return true; } // 若之前存在未正常结束的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(); return true; }resumeTopActivityInnerLocked函数比较繁琐,但整体来讲应该只有两个比较关键的地方:
如果mResumedActivity不为空,则需要先暂停这个Activity。mResumedActivity代表当前已经存在于界面的Activity。当需要启动一个新的Activity时,需要先停止当前的Activity。这部分工作由startPausingLocked函数来完成。当前的Activity被中断后,将重新启动新的Activity。当mResumedActivity为空时,若待启动的Activity对应的进程已经存在,那么仅需要重新启动该Activity;否则,需要调用ActivityStackSupervisor的startSpecificActivityLocked函数,启动整个进程。 接下来看startSpecificActivityLocked函数 // frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java void startSpecificActivityLocked(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) { // 转调用 return startProcessLocked(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函数 final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride); checkTime(startTime, "startProcess: done starting proc!"); return success ? app : null; }这段代码主要获取了记录进程的ProcessRecord,接下来看重载的startProcessLocked函数
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java private final boolean startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) { if (app.pendingStart) { return true; } long startTime = SystemClock.elapsedRealtime(); // 启动一个进程 // 若AMS之前维持着这个进程的pid信息,那么现在需要移除 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用于保存那些在系统还没有准备好就提前请求启动的ProcessRecord mProcessesOnHold.remove(app); checkTime(startTime, "startProcess: starting to update cpu stats"); updateCpuStats(); checkTime(startTime, "startProcess: done updating cpu stats"); try { try { //通过PKMS检查待启动进程对应的package是否满足启动条件 final int userId = UserHandle.getUserId(app.uid); AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } int uid = app.uid; int[] gids = null; int mountExternal = Zygote.MOUNT_EXTERNAL_NONE; if (!app.isolated) { int[] permGids = null; try { checkTime(startTime, "startProcess: getting gids from package manager"); // 通过PKMS得到进程对应的Gid final IPackageManager pm = AppGlobals.getPackageManager(); permGids = pm.getPackageGids(app.info.packageName, MATCH_DEBUG_TRIAGED_MISSING, app.userId); StorageManagerInternal storageManagerInternal = LocalServices.getService( StorageManagerInternal.class); // 这里应该是判断进程对外部存储设备的访问模式 mountExternal = storageManagerInternal.getExternalStorageMountMode(uid, app.info.packageName); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } // 讲进程的gid信息保存在gids数组中 /* * Add shared application and profile GIDs so applications can share some * resources like shared libraries and access user-wide resources */ // if (ArrayUtils.isEmpty(permGids)) { gids = new int[3]; } else { gids = new int[permGids.length + 3]; System.arraycopy(permGids, 0, gids, 3, permGids.length); } gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid)); gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid)); gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid)); // Replace any invalid GIDs if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2]; if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2]; } checkTime(startTime, "startProcess: building args"); ... // ABI表示应用程序二进制接口,ABI精确地定义了你的应用程序及其代码期在运行时如何和系统交互 String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi; if (requiredAbi == null) { requiredAbi = Build.SUPPORTED_ABIS[0]; } String instructionSet = null; if (app.info.primaryCpuAbi != null) { // 得到对应的指令集 instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi); } 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); // //指定反射的className // Start the process. It will either succeed and return a result containing // the PID of the new process, or else throw a RuntimeException. final String entryPoint = "android.app.ActivityThread"; return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); } catch (RuntimeException e) { ... } }该函数中主要配置了创建进程的一些参数,继续看重载的startProcessLocked函数
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) { // 在保存ProcessRecord中保存进程信息 app.pendingStart = true; app.killedByAm = false; app.removed = false; app.killed = false; final long startSeq = app.startSeq = ++mProcStartSeqCounter; app.setStartParams(uid, hostingType, hostingNameStr, seInfo, startTime); if (mConstants.FLAG_PROCESS_START_ASYNC) { if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES, "Posting procStart msg for " + app.toShortString()); mProcStartHandler.post(() -> { try { synchronized (ActivityManagerService.this) { final String reason = isProcStartValidLocked(app, startSeq); if (reason != null) { Slog.w(TAG_PROCESSES, app + " not valid anymore," + " don't start process, " + reason); app.pendingStart = false; return; } app.usingWrapper = invokeWith != null || SystemProperties.get("wrap." + app.processName) != null; mPendingStarts.put(startSeq, app); } final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime); synchronized (ActivityManagerService.this) { handleProcessStartedLocked(app, startResult, startSeq); } } catch (RuntimeException e) { synchronized (ActivityManagerService.this) { Slog.e(TAG, "Failure starting process " + app.processName, e); mPendingStarts.remove(startSeq); app.pendingStart = false; forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false, false, true, false, false, UserHandle.getUserId(app.userId), "start failure"); } } }); return true; } else { try { // 调用startProcess函数 final ProcessStartResult startResult = startProcess(hostingType, entryPoint, app, uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper, startSeq, false); } catch (RuntimeException e) { Slog.e(TAG, "Failure starting process " + app.processName, e); app.pendingStart = false; forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false, false, true, false, false, UserHandle.getUserId(app.userId), "start failure"); } return app.pid > 0; } }继续看startProcess函数
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java private ProcessStartResult startProcess(String hostingType, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) { try { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName); checkTime(startTime, "startProcess: asking zygote to start proc"); final ProcessStartResult startResult; if (hostingType.equals("webview_service")) { startResult = startWebView(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); } else { //Process.java的start函数,将通过socket发送消息给zygote //zygote将派生出一个子进程,子进程将通过反射调用ActivityThread的main函数 //注意此时传递给zygote的参数并没有包含任何与Activity相关的信息 startResult = Process.start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); } checkTime(startTime, "startProcess: returned from zygote!"); return startResult; } finally { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } }至此,startSpecificActivityLocked函数分析完毕,Android系统开始通过zygote创建应用进程。应用进程创建完毕之后会回调ActivityThread的main函数。下面整理一下整个启动流程。