Activity启动过程详解(Android 12源码分析)

Activity的启动方式

启动一个Activity,通常有两种情况,一种是在应用内部启动Activity,另一种是Launcher启动
1、应用内启动
通过startActivity来启动Activity
启动流程:
一、Activity启动的发起
二、Activity的管理——ATMS
三、线程切换即消息处理——mH
四、Activity启动核心实现——初始化及生命周期
2、Launcher进程启动
Launcher就是我们桌面程序,当系统开机后,Launcher也随之被启动,然后将已经安装的app显示在桌面上,等到点击某个app的时候就会fork一个新的进程,然后启动Activity
启动流程:
一、Activity启动的发起
二、Activity的管理——ATMS
三、应用进程的创建
四、根Activity 的启动

启动Activity的流程大致分为下面5个阶段
一、A进程start ActivityB
二、解析ActivityB启动参数
三、由Task管理和启动Activity
四、把AMS里面对应的application和Activity生命周期的事务在ActivityStackSupervisor里面将事务封装到ClientTransaction
五、在B进程中解析ClientTransaction的命令执行Activity的生命周期

startActivity启动流程所涉及的类:

frameworks\base\core\java\android\content/Context.java	frameworks\base\core\java\android\content/ContextWrapper.java	frameworks\base\core\java\android\app/ContextImpl.java	frameworks\base\core\java\android\app/Instrumentation.java	frameworks\base\services\core\java\com\android\server\wm/ActivityTaskManagerService.java	frameworks\base\services\core\java\com\android\server\wm/ActivityStarter.javaE:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/RootWindowContainer.javaE:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/Task.javaE:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/TaskFragment.javaE:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/ActivityTaskSupervisor.javaE:\AOSP_12\frameworks\base\core\java\android\app\servertransaction/ClientTransaction.javaE:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/ActivityTaskManagerService.javaE:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/ClientLifecycleManager.javaE:\AOSP_12\frameworks\base\core\java\android\app/IApplicationThread.aidlE:\AOSP_12\frameworks\base\core\java\android\app/ActivityThread.javaE:\AOSP_12\frameworks\base\core\java\android\app/ClientTransactionHandler.javaE:\AOSP_12\frameworks\base\core\java\android\app\servertransaction/TransactionExecutor.javaE:\AOSP_12\frameworks\base\core\java\android\app\servertransaction/ActivityLifecycleItem.javaE:\AOSP_12\frameworks\base\core\java\android\app\servertransaction/LaunchActivityItem.javaE:\AOSP_12\frameworks\base\core\java\android\app\servertransaction/ClientTransactionItem.javaClientTransactionItem的所有子类或者相关类均在 frameworks/base/core/java/android/app/servertransaction/目录下E:\AOSP_12\frameworks\base\services\core\java\com\android\server\am/ActivityManagerService.javaE:\AOSP_12\frameworks\base\services\core\java\com\android\server\am/ProcessList.javaE:\AOSP_12\frameworks\base\core\java\android\os/Process.javaE:\AOSP_12\frameworks\base\core\java\android\os/ZygoteProcess.java

一、Activity的启动的发起

启动Activity先从startActivity开始,点击startActivity进入ContextWrapper类中由于mBase对象是context,Context的实现类为ContextImpl,所以直接看ContextImpl类中的startActivity方法

   @Overridepublic void startActivity(Intent intent, Bundle options) {//判断uid是不是System_uidwarnIfCallingFromSystemProcess();// Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is// generally not allowed, except if the caller specifies the task id the activity should// be launched in. A bug was existed between N and O-MR1 which allowed this to work. We// maintain this for backwards compatibility.final int targetSdkVersion = getApplicationInfo().targetSdkVersion;if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0&& (targetSdkVersion < Build.VERSION_CODES.N|| targetSdkVersion >= Build.VERSION_CODES.P)&& (options == null|| ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {throw new AndroidRuntimeException("Calling startActivity() from outside of an Activity "+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."+ " Is this really what you want?");}//mMainThread为ActivityThread,获取的getInstrumentation()为Instrumentation				mMainThread.getInstrumentation().execStartActivity(getOuterContext(), mMainThread.getApplicationThread(), null,(Activity) null, intent, -1, options);}

看到里面调用了mMainThread.getInstrumentation().execStartActivity方法,其中mMainThread是ActivityThread,ActivityThread继承ClientTransactionHandler实现ActivityThreadInternal
是Activity运行的主进程,它管理应用程序进程中主线程中执行的调度和执行活动、广播以及活动管理请求的其他操作。而Instrumentation具有跟踪application及activity生命周期的功能,用于Android应用测试框架中代码检测。接着看mInstrumentation.execStartActivity方法:

  @UnsupportedAppUsagepublic ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, String target,Intent intent, int requestCode, Bundle options) {IApplicationThread whoThread = (IApplicationThread) contextThread;if (mActivityMonitors != null) {synchronized (mSync) {final int N = mActivityMonitors.size();for (int i=0; i<N; i++) {final ActivityMonitor am = mActivityMonitors.get(i);ActivityResult result = null;if (am.ignoreMatchingSpecificIntents()) {if (options == null) {options = ActivityOptions.makeBasic().toBundle();}result = am.onStartActivity(who, intent, options);}if (result != null) {am.mHits++;return result;} else if (am.match(who, null, intent)) {am.mHits++;if (am.isBlocking()) {return requestCode >= 0 ? am.getResult() : null;}break;}}}}try {intent.migrateExtraStreamToClipData(who);intent.prepareToLeaveProcess(who);//	这里获取了ATMS代理对象IActivityTaskManager,拿到ATMS代理对象就可以跨进程调用ATMS的startActivityint result = ActivityTaskManager.getService().startActivity(whoThread,who.getOpPackageName(), who.getAttributionTag(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()), token, target,requestCode, 0, null, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;}

可以看到Activity的启动又交给了ActivityTaskManager.getService()

    public static IActivityTaskManager getService() {return IActivityTaskManagerSingleton.get();}@UnsupportedAppUsage(trackingBug = 129726065)private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =new Singleton<IActivityTaskManager>() {@Overrideprotected IActivityTaskManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);return IActivityTaskManager.Stub.asInterface(b);}};

这里是获取一个跨进程的服务,获取的服务是ActivityTaskManagerService(ATMS),它继承于IActivityTaskManager.stub,是一个Bindder对象,并且是通过单例提供服务的,ATMS是用于管理Activity及其容器(任务,堆栈、显示等)的系统服务,运行在系统服务进程(system_server)之中。

二 Activity的管理——ATMS

在ActivityTaskManagerService里面调用startActivity方法,如下:

   @Overridepublic final int startActivity(IApplicationThread caller, String callingPackage,String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,Bundle bOptions) {return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId());}@Overridepublic int startActivityAsUser(IApplicationThread caller, String callingPackage,String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,Bundle bOptions, int userId) {return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,true /*validateIncomingUser*/);}private int startActivityAsUser(IApplicationThread caller, String callingPackage,@Nullable String callingFeatureId, Intent intent, String resolvedType,IBinder resultTo, String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {assertPackageMatchesCallingUid(callingPackage);enforceNotIsolatedCaller("startActivityAsUser");userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");// TODO: Switch to user app stacks here.//在此处切换到用户应用程序堆栈。//getActivityStartController().obtainStarter()返回的是ActivityStarter对象//采用工厂设计模式+享元设计+链式调用return getActivityStartController().obtainStarter(intent, "startActivityAsUser").setCaller(caller)//调用方的AppThread的IBinder.setCallingPackage(callingPackage)//调用方的包名.setCallingFeatureId(callingFeatureId).setResolvedType(resolvedType)//调用type.setResultTo(resultTo)//调用方的ActivityClientrecord的binder(实际上是AMS的ActivityRecord 对应在APP端的binder对象).setResultWho(resultWho)//调用方的标识.setRequestCode(requestCode)//需要返回的requestCode.setStartFlags(startFlags)//启动标志位.setProfilerInfo(profilerInfo)//启动时带上的权限文件对象.setActivityOptions(bOptions)//ActivityOptions的Activity的启动项,在一般的APP中此时是null.setUserId(userId)//是否是同步打开Activity 默认一般是rue.execute();//执行方法}

我们可以看到startActivity最终调用到startActivityAsUser方法,在内部将所有点的参数都交给了ActivityStarter,该类包含了启动的所有逻辑,比如Intent的解析以及任务栈等。接着调用了obtainStarter,该方法通过工厂模式创建了ActivityStarter对象。如下:

 @VisibleForTestingActivityStartController(ActivityTaskManagerService service, ActivityTaskSupervisor supervisor,Factory factory) {mService = service;mSupervisor = supervisor;mFactory = factory;mFactory.setController(this);mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service.mGlobalLock,service.mH);}/*** @return A starter to configure and execute starting an activity. It is valid until after*         {@link ActivityStarter#execute} is invoked. At that point, the starter should be*         considered invalid and no longer modified or used.*/ActivityStarter obtainStarter(Intent intent, String reason) {return mFactory.obtain().setIntent(intent).setReason(reason);}void onExecutionComplete(ActivityStarter starter) {if (mLastStarter == null) {mLastStarter = mFactory.obtain();}mLastStarter.set(starter);mFactory.recycle(starter);}static class DefaultFactory implements Factory {/*** The maximum count of starters that should be active at one time:* 1. last ran starter (for logging and post activity processing)* 2. current running starter* 3. starter from re-entry in (2)**/private final int MAX_STARTER_COUNT = 3;//ActivitySatrter 最大数量private ActivityStartController mController;private ActivityTaskManagerService mService;private ActivityTaskSupervisor mSupervisor;private ActivityStartInterceptor mInterceptor;//同步池private SynchronizedPool<ActivityStarter> mStarterPool =new SynchronizedPool<>(MAX_STARTER_COUNT);DefaultFactory(ActivityTaskManagerService service,ActivityTaskSupervisor supervisor, ActivityStartInterceptor interceptor) {mService = service;mSupervisor = supervisor;mInterceptor = interceptor;}@Overridepublic void setController(ActivityStartController controller) {mController = controller;}@Overridepublic ActivityStarter obtain() {//从同步池中获取ActivityStarter对象ActivityStarter starter = mStarterPool.acquire();if (starter == null) {if (mService.mRootWindowContainer == null) {throw new IllegalStateException("Too early to start activity.");}starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);}return starter;}@Overridepublic void recycle(ActivityStarter starter) {starter.reset(true /* clearRequest*/);mStarterPool.release(starter);}}

可以看到,默认的工厂在提供了一个容量为3的同步缓存池来缓存ActivityStarter对象,该对象创建完成之后,ActivityTaskManagerService就会将接下来启动Activity的操作交给ActivityStarter来完成

    int execute() {try {// Refuse possible leaked file descriptors//拒绝可能泄露的文件描述符if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) {throw new IllegalArgumentException("File descriptors passed in Intent");}..省略部分代码...res = executeRequest(mRequest);//开始执行请求..省略部分代码...return getExternalResult(res);}} finally {onExecutionComplete();//在ActivityStartController清除数据放回startPool池子中。}}/*** Executing activity start request and starts the journey of starting an activity. Here* begins with performing several preliminary checks. The normally activity launch flow will* go through {@link #startActivityUnchecked} to {@link #startActivityInner}.该方法会进行一些校验和判断权限,包括进程检查,intent检查,权限检查等。后面就会创建ActivityRecord,每个Activity都会对应一个ActivityRecord对象,接着就会调用startActivityUnchecked方法对要启动的Activity做任务栈管理。*/private int executeRequest(Request request) {...省略部分代码...//创建出我们的目标ActivityRecord对象,存到传入数组0索引上final ActivityRecord r = new ActivityRecord.Builder(mService).setCaller(callerApp).setLaunchedFromPid(callingPid).setLaunchedFromUid(callingUid).setLaunchedFromPackage(callingPackage).setLaunchedFromFeature(callingFeatureId).setIntent(intent).setResolvedType(resolvedType).setActivityInfo(aInfo).setConfiguration(mService.getGlobalConfiguration()).setResultTo(resultRecord).setResultWho(resultWho).setRequestCode(requestCode).setComponentSpecified(request.componentSpecified).setRootVoiceInteraction(voiceSession != null).setActivityOptions(checkedOptions).setSourceRecord(sourceRecord).build();mLastStartActivityRecord = r;...省略部分代码....//启动最后需要启动的activity,也就是当前activitymLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,inTask, inTaskFragment, restrictedBgActivity, intentGrants);...省略部分代码....return mLastStartActivityResult;}

在executeRequest方法中会进行一些校验和判断权限,包括进程检测,intent检查,权限检查等,后面会创建ActivityRecord,每个Activity都会对应一个ActivityRecord对象,接着就会调用startActivityUnChecked方法对要启动的Activity做任务栈管理。

 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask,TaskFragment inTaskFragment, boolean restrictedBgActivity,NeededUriGrants intentGrants) {...省略部分代码...
//在大多数初步检查已经完成的情况下开始进行下一步确认拥有必要的权限。startActivityInner()用来检查启动所必须要有的权限。result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, inTaskFragment, restrictedBgActivity,intentGrants);startResultSuccessful = ActivityManager.isStartResultSuccessful(result);final boolean taskAlwaysOnTop = options != null && options.getTaskAlwaysOnTop();// Apply setAlwaysOnTop when starting an Activity is successful regardless of creating// a new Activity or recycling the existing Activity.if (taskAlwaysOnTop && startResultSuccessful) {final Task targetRootTask =mTargetRootTask != null ? mTargetRootTask : mTargetTask.getRootTask();targetRootTask.setAlwaysOnTop(true);}} finally {..省略部分代码...}}postStartActivityProcessing(r, result, startedActivityRootTask);return result;}

在大多数初步检查已经完成的情况下开始进行下一步确认拥有必要的权限。核心方法就是调用startActivityInner()用来检查启动所必须要有的权限

int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask,TaskFragment inTaskFragment, boolean restrictedBgActivity,NeededUriGrants intentGrants) {//初始化设置,mStartActivity,mLaunchMode等setInitialState(r, options, inTask, inTaskFragment, doResume, startFlags, sourceRecord,voiceSession, voiceInteractor, restrictedBgActivity);//计算启动Activity的Flag值,判断启动模式,并且在mLaunchFlags上追加对应标记computeLaunchingTaskFlags();//计算源Activity所在的栈computeSourceRootTask();//设置LaunchFlags到intent上,也就是设置启动模式mIntent.setFlags(mLaunchFlags);// Get top task at beginning because the order may be changed when reusing existing task.final Task prevTopTask = mPreferredTaskDisplayArea.getFocusedRootTask();//决定是否应将新Activity插入Task中。返回null,如果不是则应将新Activity添加到其中的task进行Activity记录。//查找可用的任务栈final Task reusedTask = getReusableTask();// If requested, freeze the task listif (mOptions != null && mOptions.freezeRecentTasksReordering()&& mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid)&& !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) {mFrozeTaskList = true;mSupervisor.mRecentTasks.setFreezeTaskListReordering();}// Compute if there is an existing task that should be used for.//reusedTask为null则计算是否存在可以使用的任务栈final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();//是否需要创建栈final boolean newTask = targetTask == null;mTargetTask = targetTask;computeLaunchParams(r, sourceRecord, targetTask);// Check if starting activity on given task or on a new task is allowed.//检查是否允许在给定的Task或者新的Task上启动Activityint startResult = isAllowedToStart(r, newTask, targetTask);if (startResult != START_SUCCESS) {return startResult;}final ActivityRecord targetTaskTop = newTask? null : targetTask.getTopNonFinishingActivity();if (targetTaskTop != null) {// Recycle the target task for this launch.startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);if (startResult != START_SUCCESS) {return startResult;}} else {mAddingToTask = true;}// If the activity being launched is the same as the one currently at the top, then// we need to check if it should only be launched once.//如果正在启动的Activity与当前位于栈顶的Activity相同//则需要检查它是否应该只启动一次final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();if (topRootTask != null) {startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);if (startResult != START_SUCCESS) {return startResult;}}//复用或者创建新栈if (mTargetRootTask == null) {mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);}if (newTask) {//新建一个Taskfinal Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)? mSourceRecord.getTask() : null;//将Activity放入新建的任务栈setNewTask(taskToAffiliate);} else if (mAddingToTask) {//复用之前的TaskaddOrReparentStartingActivity(targetTask, "adding to task");}if (!mAvoidMoveToFront && mDoResume) {mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.mInternal.isDreaming()) {// Launching underneath dream activity (fullscreen, always-on-top). Run the launch-// -behind transition so the Activity gets created and starts in visible state.mLaunchTaskBehind = true;r.mLaunchTaskBehind = true;}}mService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants,mStartActivity.getUriPermissionsLocked());if (mStartActivity.resultTo != null && mStartActivity.resultTo.info != null) {// we need to resolve resultTo to a uid as grantImplicitAccess deals explicitly in UIDsfinal PackageManagerInternal pmInternal =mService.getPackageManagerInternalLocked();final int resultToUid = pmInternal.getPackageUid(mStartActivity.resultTo.info.packageName, 0 /* flags */,mStartActivity.mUserId);pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent,UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/,resultToUid /*visible*/, true /*direct*/);}final Task startedTask = mStartActivity.getTask();if (newTask) {EventLogTags.writeWmCreateTask(mStartActivity.mUserId, startedTask.mTaskId);}mStartActivity.logStartActivity(EventLogTags.WM_CREATE_ACTIVITY, startedTask);mStartActivity.getTaskFragment().clearLastPausedActivity();mRootWindowContainer.startPowerModeLaunchIfNeeded(false /* forceSend */, mStartActivity);final boolean isTaskSwitch = startedTask != prevTopTask && !startedTask.isEmbedded();//创建启动黑白屏windowmTargetRootTask.startActivityLocked(mStartActivity,topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,isTaskSwitch, mOptions, sourceRecord);if (mDoResume) {final ActivityRecord topTaskActivity = startedTask.topRunningActivityLocked();if (!mTargetRootTask.isTopActivityFocusable()|| (topTaskActivity != null && topTaskActivity.isTaskOverlay()&& 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.// Passing {@code null} as the start parameter ensures all activities are made// visible.mTargetRootTask.ensureActivitiesVisible(null /* starting */,0 /* configChanges */, !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.mTargetRootTask.mDisplayContent.executeAppTransition();} else {// If the target root-task was not previously focusable (previous top running// activity on that root-task was not visible) then any prior calls to move the// root-task to the will not update the focused root-task.  If starting the new// activity now allows the task root-task to be focusable, then ensure that we// now update the focused root-task accordingly.if (mTargetRootTask.isTopActivityFocusable()&& !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {mTargetRootTask.moveToFront("startActivityInner");}//启动栈中顶部的ActivitymRootWindowContainer.resumeFocusedTasksTopActivities(mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);}}mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);// Update the recent tasks list immediately when the activity startsmSupervisor.mRecentTasks.add(startedTask);mSupervisor.handleNonResizableTaskIfNeeded(startedTask,mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);return START_SUCCESS;}

在上面方法中,根据启动模式计算出flag,然后在根据flag等条件判断要启动的Activity的ActivityRecord是需要新创建Task栈还是加入到现有的Task栈中。在位Activity准备好Task栈之后,调用了mRootWindowContainer.resumeFocuredTasksTopActivities方法。
RootWindowContainer是窗口容器(WindowContainer)的根容器,管理所有的窗口容器,设备上所有的窗口(Window)显示器(Display)都是由它来管理的
下面看mRootWindowContainer.resumeFocursedTasksTopActivities方法的具体操作

  boolean resumeFocusedTasksTopActivities(Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,boolean deferPause) {if (!mTaskSupervisor.readyToResume()) {return false;}boolean result = false;if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()|| getTopDisplayFocusedRootTask() == targetRootTask)) {result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,deferPause);}for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {final DisplayContent display = getChildAt(displayNdx);final boolean curResult = result;boolean[] resumedOnDisplay = new boolean[1];display.forAllRootTasks(rootTask -> {final ActivityRecord topRunningActivity = rootTask.topRunningActivity();if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {return;}if (rootTask == targetRootTask) {// Simply update the result for targetRootTask because the targetRootTask// had already resumed in above. We don't want to resume it again,// especially in some cases, it would cause a second launch failure// if app process was dead.resumedOnDisplay[0] |= curResult;return;}if (rootTask.getDisplayArea().isTopRootTask(rootTask)&& topRunningActivity.isState(RESUMED)) {// Kick off any lingering app transitions form the MoveTaskToFront// operation, but only consider the top task and root-task on that// display.rootTask.executeAppTransition(targetOptions);} else {resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);}});result |= resumedOnDisplay[0];if (!resumedOnDisplay[0]) {// In cases when there are no valid activities (e.g. device just booted or launcher// crashed) it's possible that nothing was resumed on a display. Requesting resume// of top activity in focused root task explicitly will make sure that at least home// activity is started and resumed, and no recursion occurs.//获取当前屏幕设备的焦点任务栈final Task focusedRoot = display.getFocusedRootTask();if (focusedRoot != null) {//如果焦点任务栈不为空则唤醒顶部的Activityresult |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions);} else if (targetRootTask == null) {//否则唤醒首页Activityresult |= resumeHomeActivity(null /* prev */, "no-focusable-task",display.getDefaultTaskDisplayArea());}}}return result;}

mRootWindowContainer.resumeFocusedStacksToActivities()方法会恢复对应任务栈顶部的Activity,方法中会检查一些可见性相关的属性,后转交给Task调用resumeTopActivityUncheckedLocked方法来继续启动流程。

 /*/**	确保恢复根task中的顶部activity**/@GuardedBy("mService")boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,boolean deferPause) {if (mInResumeTopActivity) {// Don't even start recursing.return false;}boolean someActivityResumed = false;try {// Protect against recursion.mInResumeTopActivity = true;if (isLeafTask()) {if (isFocusableAndVisible()) {//继续调用resumeTopActivityInnerLocked方法someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);}} else {int idx = mChildren.size() - 1;while (idx >= 0) {final Task child = (Task) getChildAt(idx--);if (!child.isTopActivityFocusable()) {continue;}if (child.getVisibility(null /* starting */)!= TASK_FRAGMENT_VISIBILITY_VISIBLE) {break;}someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,deferPause);// Doing so in order to prevent IndexOOB since hierarchy might changes while// resuming activities, for example dismissing split-screen while starting// non-resizeable activity.if (idx >= mChildren.size()) {idx = mChildren.size() - 1;}}}// 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 ActivityTaskSupervisor#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 ActivityTaskSupervisor#checkReadyForSleepLocked} is skipped.final ActivityRecord next = topRunningActivity(true /* focusableOnly */);if (next == null || !next.canTurnScreenOn()) {checkReadyForSleep();}} finally {mInResumeTopActivity = false;}return someActivityResumed;}/** @see #resumeTopActivityUncheckedLocked(ActivityRecord, ActivityOptions, boolean) */@GuardedBy("mService")boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */);}/*** Task用来描述一个Activity的任务栈*/@GuardedBy("mService")private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,boolean deferPause) {if (!mAtmService.isBooting() && !mAtmService.isBooted()) {// Not ready yet!return false;}//在当前Task栈中找到最上层正在运行的Activity//如果这个Activity没有获取焦点,那这个Activity将会被重新启动//获取当前顶部正在运行的Activityfinal ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);if (topActivity == null) {// There are no activities left in this task, let's look somewhere else.//如果根任务栈为空则返回下一个焦点Activityreturn resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);}final boolean[] resumed = new boolean[1];//获取当前顶部正在运行的Activity的TaskFragmentfinal TaskFragment topFragment = topActivity.getTaskFragment();//唤醒resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);forAllLeafTaskFragments(f -> {if (topFragment == f) {return;}if (!f.canBeResumed(null /* starting */)) {return;}//调用TaskFragment的一个关键方法resumeTopActivity来继续唤醒顶部Activityresumed[0] |= f.resumeTopActivity(prev, options, deferPause);}, true);return resumed[0];}

跟踪代码执行到TaskFragment

    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,boolean deferPause) {ActivityRecord next = topRunningActivity(true /* focusableOnly */);if (next == null || !next.canResumeByCompat()) {return false;}next.delayedResume = false;final TaskDisplayArea taskDisplayArea = getDisplayArea();// If the top activity is the resumed one, nothing to do.if (mResumedActivity == next && next.isState(RESUMED)&& taskDisplayArea.allResumedActivitiesComplete()) {// Make sure we have executed any pending transitions, since there// should be nothing left to do at this point.executeAppTransition(options);// For devices that are not in fullscreen mode (e.g. freeform windows), it's possible// we still want to check if the visibility of other windows have changed (e.g. bringing// a fullscreen window forward to cover another freeform activity.)if (taskDisplayArea.inMultiWindowMode()) {taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,false /* preserveWindows */, true /* notifyClients */);}ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity "+ "resumed %s", next);return false;}// If we are currently pausing an activity, then don't do anything until that is done.final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();if (!allPausedComplete) {ProtoLog.v(WM_DEBUG_STATES,"resumeTopActivity: Skip resume: some activity pausing.");return false;}// If we are sleeping, and there is no resumed activity, and the top activity is paused,// well that is the state we want.if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {// Make sure we have executed any pending transitions, since there// should be nothing left to do at this point.executeAppTransition(options);ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Going to sleep and"+ " all paused");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 (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {Slog.w(TAG, "Skipping resume of top activity " + next+ ": user " + next.mUserId + " is stopped");return false;}// The activity may be waiting for stop, but that is no longer// appropriate for it.mTaskSupervisor.mStoppingActivities.remove(next);if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid);ActivityRecord lastResumed = null;final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTaskFragment().asTask()) {// 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.lastResumed = lastFocusedRootTask.getTopResumedActivity();}boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);if (mResumedActivity != null) {ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Pausing %s", mResumedActivity);//暂停栈顶的Activitypausing |= startPausing(mTaskSupervisor.mUserLeaving, false /* uiSleeping */,next, "resumeTopActivity");}if (pausing) {ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: 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.//要启动的Activity已存在,且不需要重新创建,例如设置singleTask或singleTop启动模式//next就是要启动的这个ActivityRecord,它是一个全新的ActivityRecord,所以这个地方//返回值为falseif (next.attachedToProcess()) {//为falsenext.app.updateProcessInfo(false /* updateServiceConnectionActivities */,true /* activityChange */, false /* updateOomAdj */,false /* addPendingTopUid */);} else if (!next.isProcessRunning()) {// Since the start-process is asynchronous, if we already know the process of next// activity isn't running, we can start the process earlier to save the time to wait// for the current activity to be paused.final boolean isTop = this == taskDisplayArea.getFocusedRootTask();mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,isTop ? "pre-top-activity" : "pre-activity");}if (lastResumed != null) {lastResumed.setWillCloseOrEnterPip(true);}return true;} else if (mResumedActivity == next && next.isState(RESUMED)&& taskDisplayArea.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);ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity resumed "+ "(dontWaitForPause) %s", next);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()) {mTaskSupervisor.finishNoHistoryActivitiesIfNeeded(next);}if (prev != null && prev != next && next.nowVisible) {// 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+ ", nowVisible=" + next.nowVisible);}} else {if (DEBUG_SWITCH) {Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev+ ", nowVisible=" + next.nowVisible);}}}// Launching this app's activity, make sure the app is no longer// considered stopped.try {mTaskSupervisor.getActivityMetricsLogger().notifyBeforePackageUnstopped(next.packageName);mAtmService.getPackageManager().setPackageStoppedState(next.packageName, false, next.mUserId); /* 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;final DisplayContent dc = taskDisplayArea.mDisplayContent;if (prev != null) {if (prev.finishing) {if (DEBUG_TRANSITION) {Slog.v(TAG_TRANSITION, "Prepare close transition: prev=" + prev);}if (mTaskSupervisor.mNoAnimActivities.contains(prev)) {anim = false;dc.prepareAppTransition(TRANSIT_NONE);} else {dc.prepareAppTransition(TRANSIT_CLOSE);}prev.setVisibility(false);} else {if (DEBUG_TRANSITION) {Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev);}if (mTaskSupervisor.mNoAnimActivities.contains(next)) {anim = false;dc.prepareAppTransition(TRANSIT_NONE);} else {dc.prepareAppTransition(TRANSIT_OPEN,next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0);}}} else {if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");if (mTaskSupervisor.mNoAnimActivities.contains(next)) {anim = false;dc.prepareAppTransition(TRANSIT_NONE);} else {dc.prepareAppTransition(TRANSIT_OPEN);}}//activity动画if (anim) {next.applyOptionsAnimation();} else {next.abortAndClearOptionsAnimation();}mTaskSupervisor.mNoAnimActivities.clear();//进程存在if (next.attachedToProcess()) {//为falseif (DEBUG_SWITCH) {Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.stopped+ " visibleRequested=" + next.mVisibleRequested);}// 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 = inMultiWindowMode()|| mLastPausedActivity != null && !mLastPausedActivity.occludesParent();// This activity is now becoming visible.if (!next.mVisibleRequested || next.stopped || lastActivityTranslucent) {next.setVisibility(true);}// schedule launch ticks to collect information about slow apps.next.startLaunchTickingLocked();ActivityRecord lastResumedActivity =lastFocusedRootTask == null ? null: lastFocusedRootTask.getTopResumedActivity();final ActivityRecord.State lastState = next.getState();mAtmService.updateCpuStats();ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);next.setState(RESUMED, "resumeTopActivity");// Have the window manager re-evaluate the orientation of// the screen based on the new activity order.boolean notUpdated = true;// Activity should also be visible if set mLaunchTaskBehind to true (see// ActivityRecord#shouldBeVisibleIgnoringKeyguard()).if (shouldBeVisible(next)) {// We have special rotation behavior when here is some active activity that// requests specific orientation or 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. Otherwise the following call to update// the orientation may cause incorrect configurations delivered to client as a// result of invisible window resize.// TODO: Remove this once visibilities are set correctly immediately when// starting an activity.notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),true /* markFrozenIfConfigChanged */, false /* deferResume */);}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 = topRunningActivity();ProtoLog.i(WM_DEBUG_STATES, "Activity config changed during resume: "+ "%s, new next: %s", next, nextNext);if (nextNext != next) {// Do over!mTaskSupervisor.scheduleResumeTopActivities();}if (!next.mVisibleRequested || next.stopped) {next.setVisibility(true);}//如果要启动的Activity进程存在,则会调用completeResumeLocked方法next.completeResumeLocked();return true;}try {//开启一个事务final ClientTransaction transaction =ClientTransaction.obtain(next.app.getThread(), next.appToken);// Deliver all pending results.ArrayList<ResultInfo> a = next.results;if (a != null) {final int size = a.size();if (!next.finishing && size > 0) {if (DEBUG_RESULTS) {Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);}transaction.addCallback(ActivityResultItem.obtain(a));}}if (next.newIntents != null) {//添加onNewIntent的callback,最终会在APP端执行onNewIntent()transaction.addCallback(NewIntentItem.obtain(next.newIntents, true /* resume */));}// Well the app will no longer be stopped.// Clear app token stopped state in window manager if needed.next.notifyAppResumed(next.stopped);EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),next.getTask().mTaskId, next.shortComponentName);mAtmService.getAppWarningsLocked().onResumeActivity(next);next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);next.abortAndClearOptionsAnimation();//设置Actiivity最终的生命周期状态为onResumetransaction.setLifecycleStateRequest(ResumeActivityItem.obtain(next.app.getReportedProcState(),dc.isNextTransitionForward()));//开始执行事务mAtmService.getLifecycleManager().scheduleTransaction(transaction);ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Resumed %s", next);} catch (Exception e) {// Whoops, need to restart this activity!ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "+ "%s", lastState, next);next.setState(lastState, "resumeTopActivityInnerLocked");// lastResumedActivity being non-null implies there is a lastStack present.if (lastResumedActivity != null) {lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");}Slog.i(TAG, "Restarting because process died: " + next);if (!next.hasBeenLaunched) {next.hasBeenLaunched = true;} else if (SHOW_APP_STARTING_PREVIEW && lastFocusedRootTask != null&& lastFocusedRootTask.isTopRootTaskInDisplayArea()) {next.showStartingWindow(false /* taskSwitch */);}//Activity的启动事务就是在realStartActivityLocked方法中启动mTaskSupervisor.startSpecificActivity(next, true, false);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);next.finishIfPossible("resume-exception", true /* oomAdj */);return true;}} else {// Whoops, need to restart this activity!if (!next.hasBeenLaunched) {next.hasBeenLaunched = true;} else {if (SHOW_APP_STARTING_PREVIEW) {next.showStartingWindow(false /* taskSwich */);}if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);}ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);//启动指定的ActivitymTaskSupervisor.startSpecificActivity(next, true, true);}return true;}

resumeTopActivity方法中主要有两个部分内容。
1、next.attachedToProcess()为true,即要启动的这个Activity已经存在,并且设置了像"singleInstance"的启动模式,无需重新创建Activity的情况下,则先通过ClientTransaction添加了一个NewIntentItem的callback,接下来通过setLifecycleStateRequestt设置了一个ResumeActivityItem对象
2、next.attachedToProcess()为false,则继续执行Activity的启动流程。

在resumeTopActivity方法中因为启动的ActivityRecord是一个全新的Activity,所以在该方法中判断next.attachedToProcess()为false,所以会调用mTaskSupervisor.StartSpecificActivity()开启指定的activity ,代码如下:

    void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {// Is this activity's application already running?//获取目标进程final WindowProcessController wpc =mService.getProcessController(r.processName, r.info.applicationInfo.uid);boolean knownToBeDead = false;//进程已经创建的话,直接启动activityif (wpc != null && wpc.hasThread()) {try {//Activity的启动事务就是在realStartActivityLoked方法中启动//如果进程存在,启动Activity并返回realStartActivityLocked(r, wpc, 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.knownToBeDead = true;}r.notifyUnknownVisibilityLaunchedForKeyguardTransition();final boolean isTop = andResume && r.isTopRunningActivity();//如果进程不存在,为app启动一个进程mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");}

在该方法中ActivityStackSupervisor.startSpecificActivity()方法中获取WindowProcessController,通过wpc.hasThread()方法判断应用进程是否已创建并运行中,其内部是通过IApplicationThread是否已经被赋值来判断的,如果已被赋值则表示应用进程已创建且运行中,此时进入判断体内部,走ActivityStackSupervisor.realStartActivityLocked()方法继续Activity的启动流程,即普通Activity的启动流程。如果未被赋值,则需要创建。在这里我们先看进程已经创建并且执行realStartActivity()方法。

   boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,boolean andResume, boolean checkConfig) throws RemoteException {//传递过来的andResume =trueif (!mRootWindowContainer.allPausedActivitiesComplete()) {// While there are activities pausing we skipping starting any new activities until// pauses are complete. NOTE: that we also do this for activities that are starting in// the paused state because they will first be resumed then paused on the client side.ProtoLog.v(WM_DEBUG_STATES,"realStartActivityLocked: Skipping start of r=%s some activities pausing...",r);return false;}final Task task = r.getTask();final Task rootTask = task.getRootTask();beginDeferResume();// The LaunchActivityItem also contains process configuration, so the configuration change// from WindowProcessController#setProcess can be deferred. The major reason is that if// the activity has FixedRotationAdjustments, it needs to be applied with configuration.// In general, this reduces a binder transaction if process configuration is changed.proc.pauseConfigurationDispatch();try {r.startFreezingScreenLocked(proc, 0);// schedule launch ticks to collect information about slow apps.r.startLaunchTickingLocked();r.setProcess(proc);// Ensure activity is allowed to be resumed after process has set.if (andResume && !r.canResumeByCompat()) {andResume = false;}r.notifyUnknownVisibilityLaunchedForKeyguardTransition();// Have the window manager re-evaluate the orientation of the screen based on the new// activity order.  Note that as a result of this, it can call back into the activity// manager with a new orientation.  We don't care about that, because the activity is// not currently running so we are just restarting it anyway.if (checkConfig) {// Deferring resume here because we're going to launch new activity shortly.// We don't want to perform a redundant launch of the same record while ensuring// configurations and trying to resume top activity of focused root task.mRootWindowContainer.ensureVisibilityAndConfig(r, r.getDisplayId(),false /* markFrozenIfConfigChanged */, true /* deferResume */);}if (mKeyguardController.checkKeyguardVisibility(r) && r.allowMoveToFront()) {// We only set the visibility to true if the activity is not being launched in// background, and is allowed to be visible based on keyguard state. This avoids// setting this into motion in window manager that is later cancelled due to later// calls to ensure visible activities that set visibility back to false.r.setVisibility(true);}final int applicationInfoUid =(r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;if ((r.mUserId != proc.mUserId) || (r.info.applicationInfo.uid != applicationInfoUid)) {Slog.wtf(TAG,"User ID for activity changing for " + r+ " appInfo.uid=" + r.info.applicationInfo.uid+ " info.ai.uid=" + applicationInfoUid+ " old=" + r.app + " new=" + proc);}// Send the controller to client if the process is the first time to launch activity.// So the client can save binder transactions of getting the controller from activity// task manager service.final IActivityClientController activityClientController =proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController;r.launchCount++;r.lastLaunchTime = SystemClock.uptimeMillis();proc.setLastActivityLaunchTime(r.lastLaunchTime);if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);final LockTaskController lockTaskController = mService.getLockTaskController();if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE|| task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV|| (task.mLockTaskAuth == LOCK_TASK_AUTH_ALLOWLISTED&& lockTaskController.getLockTaskModeState()== LOCK_TASK_MODE_LOCKED)) {lockTaskController.startLockTaskMode(task, false, 0 /* blank UID */);}try {if (!proc.hasThread()) {throw new RemoteException();}List<ResultInfo> results = null;List<ReferrerIntent> newIntents = null;if (andResume) {// We don't need to deliver new intents and/or set results if activity is going// to pause immediately after launch.results = r.results;newIntents = r.newIntents;}if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,"Launching: " + r + " savedState=" + r.getSavedState()+ " with results=" + results + " newIntents=" + newIntents+ " andResume=" + andResume);EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),task.mTaskId, r.shortComponentName);if (r.isActivityTypeHome()) {// Home process is the root process of the task.updateHomeProcess(task.getBottomMostActivity().app);}mService.getPackageManagerInternalLocked().notifyPackageUse(r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);r.forceNewConfig = false;mService.getAppWarningsLocked().onStartActivity(r);r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);// Because we could be starting an Activity in the system process this may not go// across a Binder interface which would create a new Configuration. Consequently// we have to always create a new Configuration here.final Configuration procConfig = proc.prepareConfigurationForLaunchingActivity();final MergedConfiguration mergedConfiguration = new MergedConfiguration(procConfig, r.getMergedOverrideConfiguration());r.setLastReportedConfiguration(mergedConfiguration);logIfTransactionTooLarge(r.intent, r.getSavedState());if (r.isEmbedded()) {// Sending TaskFragmentInfo to client to ensure the info is updated before// the activity creation.mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent(r.getOrganizedTaskFragment());}// Create activity launch transaction.//创建Activity启动事务//这里传入的proc.getThread会赋值给ClientTransaction的成员变量mClient//而ClientTransaction会调用mClient.scheduleTransaction(this)来执行事务//所以事务最终是调用app.thread的scheduleTransacction执行。//而这个app.thread是ActivityThread的内部类ApplicationThreadfinal ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.appToken);final boolean isTransitionForward = r.isTransitionForward();//为事务设置Callback LaunchActivityItem,在客户端时会被调用//添加LaunchActivityItemclientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),results, newIntents, r.takeOptions(), isTransitionForward,proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,r.getLaunchedFromBubble()));// Set desired final state.//生命周期对象,ActivityLifecycleItem 用来请求Activity应该到达那个生命周期final ActivityLifecycleItem lifecycleItem;if (andResume) {//需要resume的话,设置resumeActivityItem到clientTransaction中lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);} else {//将最终生命周期设置为pause状态lifecycleItem = PauseActivityItem.obtain();}//设置生命周期请求clientTransaction.setLifecycleStateRequest(lifecycleItem);// Schedule transaction.//获取生命周期管理类ClientLifeCycleManager,并执行事务mService.getLifecycleManager().scheduleTransaction(clientTransaction);if (procConfig.seq > mRootWindowContainer.getConfiguration().seq) {// If the seq is increased, there should be something changed (e.g. registered// activity configuration).proc.setLastReportedConfiguration(procConfig);}if ((proc.mInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0&& mService.mHasHeavyWeightFeature) {// This may be a heavy-weight process! Note that the package manager will ensure// that only activity can run in the main process of the .apk, which is the only// thing that will be considered heavy-weight.if (proc.mName.equals(proc.mInfo.packageName)) {if (mService.mHeavyWeightProcess != null&& mService.mHeavyWeightProcess != proc) {Slog.w(TAG, "Starting new heavy weight process " + proc+ " when already running "+ mService.mHeavyWeightProcess);}mService.setHeavyWeightProcess(r);}}} catch (RemoteException e) {if (r.launchFailed) {// This is the second time we failed -- finish activity and give up.//第二次启动失败的异常处理Slog.e(TAG, "Second failure launching "+ r.intent.getComponent().flattenToShortString() + ", giving up", e);proc.appDied("2nd-crash");r.finishIfPossible("2nd-crash", false /* oomAdj */);return false;}// This is the first time we failed -- restart process and// retry.//第一次启动失败,重试r.launchFailed = true;proc.removeActivity(r, true /* keepAssociation */);throw e;}} finally {endDeferResume();proc.resumeConfigurationDispatch();}r.launchFailed = false;// TODO(lifecycler): Resume or pause requests are done as part of launch transaction,// so updating the state should be done accordingly.if (andResume && readyToResume()) {// As part of the process of launching, ActivityThread also performs// a resume.rootTask.minimalResumeActivityLocked(r);} else {// This activity is not starting in the resumed state... which should look like we asked// it to pause+stop (but remain visible), and it has done so and reported back the// current icicle and other state.ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s "+ "(starting in paused state)", r);r.setState(PAUSED, "realStartActivityLocked");mRootWindowContainer.executeAppTransitionForAllDisplay();}// Perform OOM scoring after the activity state is set, so the process can be updated with// the latest state.proc.onStartActivity(mService.mTopProcessState, r.info);// Launch the new version setup screen if needed.  We do this -after-// launching the initial activity (that is, home), so that it can have// a chance to initialize itself while in the background, making the// switch back to it faster and look better.if (mRootWindowContainer.isTopDisplayFocusedRootTask(rootTask)) {mService.getActivityStartController().startSetupActivity();}// Update any services we are bound to that might care about whether// their client may have activities.if (r.app != null) {r.app.updateServiceConnectionActivities();}return true;}

代码如上:realStartActivityLocked方法中获取了一个ClientTransaction实例,并调用了它的addCallback方法,与上面的不同的是这里添加了一个LaunchActivityItem实例。

线程切换及消息处理——mH

ClientTransaction

ClientTransaction是包含了一系列要执行的事务项的事务。我们可以通过调用它的addCallback方法来添加一个事务项,你也可以多次调用来添加多个事务项。addCallback接收的参数类型为ClientTransactionItem,而这个ClientTransactionItem有多个子类,例如上面已经出现的NewIntentItem、LaunchActivityItem等都是其子类。
另外可以通过ClientTransactionItem的setLifecycleStateRequest方法设置Activity执行完后最终的生命周期状态,其参数的类型为ActivityLifecycleItem。ActivityLifecycleItem也是继承自ClientTransactionItem。同时ActivityLifecycleItem也有多个子类,它的每个子类都对应了Activity的一个生命周期事件。
在完成callback与LifecycleStateRequest的设置之后,便通过调用
mService.getLifecycleManager().scheduleTransaction(clientTransaction)方法开启事务项的执行。
这里的mService.getLifecycleManager()获取到的是什么呢?跟踪ActivityTaskManagerService源码我们可以找到getLifecycleManager的代码如下:

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.javaClientLifecycleManager getLifecycleManager() {return mLifecycleManager;}

可以看到,getLifecycleManager返回了一个ClientLifecycleManager的实例,并调用了scheduleTransaction方法,代码如下:

    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {final IApplicationThread client = transaction.getClient();//执行事务,会调用ClientTransaction的schedule方法transaction.schedule();if (!(client instanceof Binder)) {// If client is not an instance of Binder - it's a remote call and at this point it is// safe to recycle the object. All objects used for local calls will be recycled after// the transaction is executed on client in ActivityThread.transaction.recycle();}}/*** Schedule a single lifecycle request or callback to client activity.* @param client Target client.* @param activityToken Target activity token.* @param stateRequest A request to move target activity to a desired lifecycle state.* @throws RemoteException** @see ClientTransactionItem*/void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,@NonNull ActivityLifecycleItem stateRequest) throws RemoteException {final ClientTransaction clientTransaction = transactionWithState(client, activityToken,stateRequest);scheduleTransaction(clientTransaction);}

在schedule方法中通过mClient调用了scheduleTransaction,这里的mClient即为IApplicationThread,这个参数是在实例化ClientTransaction时传递进来的,IApplicationThread是一个AIDL类,那么通过编译后它会生成一个IApplicationThread.Stub类,在ActivityThread中ApplicationThread就是继承了IApplicationThread.Stub。所以这里实际上调用的是ApplicationThread中的scheduleTransaction方法中。

	frameworks\base\core\java\android\app/ActivityThread.java@Overridepublic void scheduleTransaction(ClientTransaction transaction) throws RemoteException {ActivityThread.this.scheduleTransaction(transaction);}

在ActivityThread的类里面发现没有实现scheduleTransaction方法,想到子类可以调用父类的方法,所以可以去ClientTransactionHandler.java类里面去查找scheduleTransaction方法

  void scheduleTransaction(ClientTransaction transaction) {//处理transaction.preExecute(this);//发送消息sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);}

这里将transaction作为参数调用了sendMessage方法。

 void sendMessage(int what, Object obj) {sendMessage(what, obj, 0, 0, false);}private void sendMessage(int what, Object obj, int arg1) {sendMessage(what, obj, arg1, 0, false);}private void sendMessage(int what, Object obj, int arg1, int arg2) {sendMessage(what, obj, arg1, arg2, false);}private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {Message msg = Message.obtain();msg.what = what;msg.obj = obj;msg.arg1 = arg1;msg.arg2 = arg2;if (async) {// 设置异步消息,会优先执行msg.setAsynchronous(true);}mH.sendMessage(msg);}

可以看到,这里最终将ClientTransaction与EXECUTE_TRANSACTION打包成一个message,并且将这个message设置成了异步消息,最终通过mH发送了出去,这里的mH是一个继承自Handler的H类,位于ActivityThread类的内部。
接下来看一下在H类的内部是如何处理这条消息的,我们搜索EXECUTE_TRANSACTION可以看到如下代码:

 case EXECUTE_TRANSACTION:final ClientTransaction transaction = (ClientTransaction) msg.obj;//执行事务mTransactionExecutor.execute(transaction);if (isSystem()) {// Client transactions inside system process are recycled on the client side// instead of ClientLifecycleManager to avoid being cleared before this// message is handled.transaction.recycle();}// TODO(lifecycler): Recycle locally scheduled transactions.break;

这里的代码很简单,通过Message拿到ClientTransaction后,然后通过TransactionExecutor的execute方法来执行ClientTransaction。

    public void execute(ClientTransaction transaction) {...省略部分代码...if (DEBUG_RESOLVER) Slog.d(TAG, transactionToString(transaction, mTransactionHandler));//执行回调executeCallbacks(transaction);//处理生命周期状态executeLifecycleState(transaction);mPendingActions.clear();if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");}

这个方法里的执行逻辑可以分为两部分:
1、通过executeCallbacks方法执行所有被添加进来的ClientTransactionItem
2、通过executeLifecycleState方法将Activity的生命周期执行到指定的状态。

executeCallbacks方法分析

executeCallbacks的代码如下:
    @VisibleForTestingpublic void executeCallbacks(ClientTransaction transaction) {final List<ClientTransactionItem> callbacks = transaction.getCallbacks();if (callbacks == null || callbacks.isEmpty()) {// No callbacks to execute, return early.return;}if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callbacks in transaction");final IBinder token = transaction.getActivityToken();ActivityClientRecord r = mTransactionHandler.getActivityClient(token);// In case when post-execution state of the last callback matches the final state requested// for the activity in this transaction, we won't do the last transition here and do it when// moving to final state instead (because it may contain additional parameters from server).final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState(): UNDEFINED;// Index of the last callback that requests some post-execution state.final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);final int size = callbacks.size();//遍历callbacks数组for (int i = 0; i < size; ++i) {//从callbacks数组中取出itemfinal ClientTransactionItem item = callbacks.get(i);if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);final int postExecutionState = item.getPostExecutionState();final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,item.getPostExecutionState());if (closestPreExecutionState != UNDEFINED) {cycleToPath(r, closestPreExecutionState, transaction);}//调用launchActivityItem的execute方法item.execute(mTransactionHandler, token, mPendingActions);item.postExecute(mTransactionHandler, token, mPendingActions);if (r == null) {// Launch activity request will create an activity record.r = mTransactionHandler.getActivityClient(token);}if (postExecutionState != UNDEFINED && r != null) {// Skip the very last transition and perform it by explicit state request instead.final boolean shouldExcludeLastTransition =i == lastCallbackRequestingState && finalState == postExecutionState;cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction);}}}

在executeCallbacks中遍历了所有的ClientTransactionItem并执行了ClientTransactionItem的execute方法。上一章我们分析了,当Activity正常启动时,通过addCallback添加的是一个LaunchActivityItem的实例。以此为例,这里会先执行LaunchActivity的execute方法,进而执行Activity的实例化即onCreate生命周期的调用。这块源码后面再分析

ClientTransactionItem

我们上文提到过ClientTransactionItem有多个实现类,这些实现类对应了Activity中不同的执行流程。例如在Activity启动时如果不需要重新创建Activity,则会通过addCallback添加了一个NewIntentItem来执行Activity的onNewIntent方法。而当需要重新创建Activity时,则传入的是一个LaunchActivityItem,用来创建并启动Activity。
ClientTransactionItem的所有子类或相关类均在framework/base/core/java/android/app/servertransaction/目录下,如下图所示:
在这里插入图片描述
上文中提到的ActivityLifecycleItem继承自ClientTransactionItem,且其子类均为Activity生命周期相关的实现,例如,StartActivityItem,ResumeActivityItem、DestoryActivityItem等。显而易见的是,这里将Activity的生命周期以及其他相关方法以面向对象的思想封装成了一个个的对象来执行。相比早些年的Android版本代码,所有生命周期以及相关方法都通过Handler的sendMessage的方法发送出来,这种面向对象的思想的逻辑更加清晰,且代码更容易维护。

executeLifecycleState方法

接着来看executeCallbacks中的executeLifecycleState方法,前面提到过,这里会将Activity执行到指定的生命周期状态。上边的代码中我们看到在Activity启动时,setLifecycleStateRequest设置的是一个ResumeActivityItem,代码如下:

   // 设置 Activity 最终的生命周期状态为 Resumetransaction.setLifecycleStateRequest(ResumeActivityItem.obtain(next.app.getReportedProcState(),dc.isNextTransitionForward()));

设置了ResumeActivityItem后,接下俩看看executeLifecycleState方法的源码:

    private void executeLifecycleState(ClientTransaction transaction) {//获取ActivityLifecycleItem,这里获取的是我们之前添加的ResumeActivityItemfinal ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();if (lifecycleItem == null) {// No lifecycle request, return early.return;}final IBinder token = transaction.getActivityToken();final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);if (DEBUG_RESOLVER) {Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "+ lifecycleItem + " for activity: "+ getShortActivityName(token, mTransactionHandler));}if (r == null) {// Ignore requests for non-existent client records for now.return;}// Cycle to the state right before the final requested state.//切换到对应的生命周期//ResumeActivityItem的getTargetState是on_RESUME第二个参数为执行完时的生命周期状态cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);// Execute the final transition with proper parameters.//执行ResumeActivityItem的executelifecycleItem.execute(mTransactionHandler, token, mPendingActions);lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);}

这段代码的关键点在于cycleToPath。同时,通过lifecycleItem.getTargetState()作为结束时的生命周期状态。由于此时设置的时一个ResumeActivityItem,它的getTargetState返回的是一个ON_RESUME的值,代码如下:

// frameworks/base/core/java/android/app/servertransaction/ResumeActivityItem.java@Overridepublic int getTargetState() {return ON_RESUME;}@Retention(RetentionPolicy.SOURCE)public @interface LifecycleState{}public static final int UNDEFINED = -1;public static final int PRE_ON_CREATE = 0;public static final int ON_CREATE = 1;public static final int ON_START = 2;public static final int ON_RESUME = 3;public static final int ON_PAUSE = 4;public static final int ON_STOP = 5;public static final int ON_DESTROY = 6;public static final int ON_RESTART = 7;

可以看到ON_RESUME的值为3。接下来看cycleToPath源码:

 private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,ClientTransaction transaction) {//获取当前Activity的生命周期,即开始时的状态final int start = r.getLifecycleState();if (DEBUG_RESOLVER) {Slog.d(TAG, tId(transaction) + "Cycle activity: "+ getShortActivityName(r.token, mTransactionHandler)+ " from: " + getStateName(start) + " to: " + getStateName(finish)+ " excludeLastState: " + excludeLastState);}//这里的start是ON_CREATE,finish 是ON_RESUME,//mHelper是TransactionExceutorHelper类的对象//调用getLifecyclePath返回的path包含ON_START和ON_RESUME//这里是Activity执行onStart函数的关键所在final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);//执行path中的相关生命周期状态的函数performLifecycleSequence(r, path, transaction);}

在这个方法中,首先获取了当前Activity生命周期状态,即开始执行getLifecyclePath时Activity的生命周期状态,由于executeLifecycleState方法是在executeCallback之后执行的,上面我们已经提到此时的Activity已经执行完成了创建流程,并执行过了onCreate的生命周期。因此,这里的start应该是ON_CREATE状态,ON_CREATE的值为1.接下来看getLifecyclePath做了什么

// frameworks/base/core/java/android/app/servertransaction/TransactionExecutorHelper.javapublic IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {if (start == UNDEFINED || finish == UNDEFINED) {throw new IllegalArgumentException("Can't resolve lifecycle path for undefined state");}if (start == ON_RESTART || finish == ON_RESTART) {throw new IllegalArgumentException("Can't start or finish in intermittent RESTART state");}if (finish == PRE_ON_CREATE && start != finish) {throw new IllegalArgumentException("Can only start in pre-onCreate state");}mLifecycleSequence.clear();// Activity 启动 时,执行到这里的 start 状态为 ON_CREATE,结束状态为 ON_RESUMEif (finish >= start) {if (start == ON_START && finish == ON_STOP) {// A case when we from start to stop state soon, we don't need to go// through the resumed, paused state.mLifecycleSequence.add(ON_STOP);} else {// 会走到这里的逻辑,将 ON_START 与 ON_RESUME 添加到数组for (int i = start + 1; i <= finish; i++) {mLifecycleSequence.add(i);}}} else { // finish < start, can't just cycle downif (start == ON_PAUSE && finish == ON_RESUME) {// Special case when we can just directly go to resumed state.mLifecycleSequence.add(ON_RESUME);} else if (start <= ON_STOP && finish >= ON_START) {// Restart and go to required state.// Go to stopped state first.for (int i = start + 1; i <= ON_STOP; i++) {mLifecycleSequence.add(i);}// RestartmLifecycleSequence.add(ON_RESTART);// Go to required statefor (int i = ON_START; i <= finish; i++) {mLifecycleSequence.add(i);}} else {// Relaunch and go to required state// Go to destroyed state first.for (int i = start + 1; i <= ON_DESTROY; i++) {mLifecycleSequence.add(i);}// Go to required statefor (int i = ON_CREATE; i <= finish; i++) {mLifecycleSequence.add(i);}}}// Remove last transition in case we want to perform it with some specific params.if (excludeLastState && mLifecycleSequence.size() != 0) {mLifecycleSequence.remove(mLifecycleSequence.size() - 1);}return mLifecycleSequence;}

根据上面分析,此时的start为ON_CREATE(值为1),而finish的值为ON_RESUME(值为2).因此,执行完getLifecyclePath后会得到一个包含了ON_START与ON_RESUME的数组。
接下来看performLifecycleSequence中的代码:

 /** Transition the client through previously initialized state sequence. *//***Activity的生命周期就是在这里进行的一个相关方法的调用。这里的成员变量mTransactionHandler是一个ClientTransactionHandler对象,在ClientTransactionHandler中这些方法都是抽象方法,这里执行的是ClientTransactionHandler的实现类ActivityThread中的handleLaunchActivity方法*/private void performLifecycleSequence(ActivityClientRecord r, IntArray path,ClientTransaction transaction) {//通过mHelper调用getLifecyclePath返回的path是ON_STARTfinal int size = path.size();//遍历数组,执行Activity的生命周期for (int i = 0, state; i < size; i++) {state = path.get(i);if (DEBUG_RESOLVER) {Slog.d(TAG, tId(transaction) + "Transitioning activity: "+ getShortActivityName(r.token, mTransactionHandler)+ " to state: " + getStateName(state));}switch (state) {case ON_CREATE:mTransactionHandler.handleLaunchActivity(r, mPendingActions,null /* customIntent */);break;case ON_START:mTransactionHandler.handleStartActivity(r, mPendingActions,null /* activityOptions */);break;case ON_RESUME:mTransactionHandler.handleResumeActivity(r, false /* finalStateRequest */,r.isForward, "LIFECYCLER_RESUME_ACTIVITY");break;case ON_PAUSE:mTransactionHandler.handlePauseActivity(r, false /* finished */,false /* userLeaving */, 0 /* configChanges */, mPendingActions,"LIFECYCLER_PAUSE_ACTIVITY");break;case ON_STOP:mTransactionHandler.handleStopActivity(r, 0 /* configChanges */,mPendingActions, false /* finalStateRequest */,"LIFECYCLER_STOP_ACTIVITY");break;case ON_DESTROY:mTransactionHandler.handleDestroyActivity(r, false /* finishing */,0 /* configChanges */, false /* getNonConfigInstance */,"performLifecycleSequence. cycling to:" + path.get(size - 1));break;case ON_RESTART:mTransactionHandler.performRestartActivity(r, false /* start */);break;default:throw new IllegalArgumentException("Unexpected lifecycle state: " + state);}}}
}

在performLifecycleSequence方法中则是遍历了这个数组。因为此时的数组中只有ON_START与ON_RESUME两个值,因此这里分别先后执行了mTransactionHandler.handleStartActivity与mTransactionHandler.handleResumeActivity,即调用了ApplicationThread的handleStartActivity与handleResumeActivity来执行Activity的onStart与onResume的生命周期。

Activity启动核心实现——Activity的创建与生命周期的执行

Activity的启动是在服务端通过添加一个LaunchActivityItem到ClientTransaction中实现的,然后通过IApplicationThread跨进程将ClientTransaction传到了客户端来执行的。客户端通过遍历ClientTransaction中的所有ClientTransactionItem,并执行了它的execute方法进而来执行Activity的创建过程。那接下来看LaunchActivityItem的execute方法调用后到底是如何执行的。

frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java@Overridepublic void execute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) {Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");ActivityClientRecord r = client.getLaunchingActivity(token);client.handleLaunchActivity(r, pendingActions, null /* customIntent */);Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);}

LaunchActivityItem的execute方法调用了ClientTransactionHandler的handleLaunchActivity,而这里的ClientTransactionHandler就是ActivityThread。ActivityThread中的handleLaunchActivity的源码如下:

frameworks/base/core/java/android/app/ActivityThread.java@Overridepublic Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {// If we are getting ready to gc after going to the background, well// we are back active so skip it.unscheduleGcIdler();mSomeActivitiesChanged = true;if (r.profilerInfo != null) {mProfiler.setProfiler(r.profilerInfo);mProfiler.startProfiling();}if (r.mPendingFixedRotationAdjustments != null) {// The rotation adjustments must be applied before handling configuration, so process// level display metrics can be adjusted.overrideApplicationDisplayAdjustments(r.token, adjustments ->adjustments.setFixedRotationAdjustments(r.mPendingFixedRotationAdjustments));}// Make sure we are running with the most recent config.mConfigurationController.handleConfigurationChanged(null, null);if (localLOGV) Slog.v(TAG, "Handling launch of " + r);// Initialize before creating the activityif (ThreadedRenderer.sRendererEnabled&& (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {HardwareRenderer.preload();}//创建WindowManagerServerWindowManagerGlobal.initialize();// Hint the GraphicsEnvironment that an activity is launching on the process.GraphicsEnvironment.hintActivityLaunch();//通过反射创建指定的Activity,并回调Activity的PerformCreate方法执行onCreatefinal Activity a = performLaunchActivity(r, customIntent);if (a != null) {r.createdConfig = new Configuration(mConfigurationController.getConfiguration());reportSizeConfigurations(r);if (!r.activity.mFinished && pendingActions != null) {pendingActions.setOldState(r.state);pendingActions.setRestoreInstanceState(true);pendingActions.setCallOnPostCreate(true);}} else {// If there was an error, for any reason, tell the activity manager to stop us.ActivityClient.getInstance().finishActivity(r.token, Activity.RESULT_CANCELED,null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY);}return a;}

在handleLaunchActivity方法中首先去初始化WindowManagerGlobal,紧接着调用了performLaunchActivity并返回了一个Activity实例,那么Activity的实例化必定是在performLaunchActivity中完成的。

Activity的实例化与onCreate的调用

看下performLaunchActivity的源码:

frameworks/base/core/java/android/app/ActivityThread.javaprivate Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {ActivityInfo aInfo = r.activityInfo;if (r.packageInfo == null) {r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,Context.CONTEXT_INCLUDE_CODE);}ComponentName component = r.intent.getComponent();if (component == null) {component = r.intent.resolveActivity(mInitialApplication.getPackageManager());r.intent.setComponent(component);}if (r.activityInfo.targetActivity != null) {component = new ComponentName(r.activityInfo.packageName,r.activityInfo.targetActivity);}ContextImpl appContext = createBaseContextForActivity(r);Activity activity = null;try {//反射创建Activityjava.lang.ClassLoader cl = appContext.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);StrictMode.incrementExpectedActivityCount(activity.getClass());r.intent.setExtrasClassLoader(cl);r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),appContext.getAttributionSource());if (r.state != null) {r.state.setClassLoader(cl);}} catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to instantiate activity " + component+ ": " + e.toString(), e);}}try {//如果没有Application,则进行创建Application app = r.packageInfo.makeApplication(false, mInstrumentation);if (localLOGV) Slog.v(TAG, "Performing launch of " + r);if (localLOGV) Slog.v(TAG, r + ": app=" + app+ ", appName=" + app.getPackageName()+ ", pkg=" + r.packageInfo.getPackageName()+ ", comp=" + r.intent.getComponent().toShortString()+ ", dir=" + r.packageInfo.getAppDir());// updatePendingActivityConfiguration() reads from mActivities to update// ActivityClientRecord which runs in a different thread. Protect modifications to// mActivities to avoid race.synchronized (mResourcesManager) {mActivities.put(r.token, r);}if (activity != null) {CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());Configuration config =new Configuration(mConfigurationController.getCompatConfiguration());if (r.overrideConfig != null) {config.updateFrom(r.overrideConfig);}if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "+ r.activityInfo.name + " with config " + config);Window window = null;if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {window = r.mPendingRemoveWindow;r.mPendingRemoveWindow = null;r.mPendingRemoveWindowManager = null;}// Activity resources must be initialized with the same loaders as the// application context.//加载资源appContext.getResources().addLoaders(app.getResources().getLoaders().toArray(new ResourcesLoader[0]));appContext.setOuterContext(activity);//调用attach方法,会在这个方法中创建Activity的PhoneWindow,并绑定对应的WindowManageractivity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback,r.assistToken, r.shareableActivityToken);if (customIntent != null) {activity.mIntent = customIntent;}r.lastNonConfigurationInstances = null;checkAndBlockForNetworkAccess();activity.mStartedActivity = false;int theme = r.activityInfo.getThemeResource();if (theme != 0) {activity.setTheme(theme);}if (r.mActivityOptions != null) {activity.mPendingOptions = r.mActivityOptions;r.mActivityOptions = null;}activity.mLaunchedFromBubble = r.mLaunchedFromBubble;activity.mCalled = false;// Assigning the activity to the record before calling onCreate() allows// ActivityThread#getActivity() lookup for the callbacks triggered from// ActivityLifecycleCallbacks#onActivityCreated() or// ActivityLifecycleCallback#onActivityPostCreated().r.activity = activity;//回调onCreate方法if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}if (!activity.mCalled) {throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() +" did not call through to super.onCreate()");}mLastReportedWindowingMode.put(activity.getActivityToken(),config.windowConfiguration.getWindowingMode());}//设置当前状态r.setState(ON_CREATE);} catch (SuperNotCalledException e) {throw e;} catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to start activity " + component+ ": " + e.toString(), e);}}return activity;}

这个方法中的主要逻辑可以分为两部分,第一部分是实例化Activity,第二部分是执行Activity的onCreate的生命周期。先看第一部分,通过Instrumentation的newActivity获取到一个Activity实例,newActivity的参数传入了一个ClassLoader和Activity的className。因此,这里实例化Activity的过程一定是通过反射实现的。查看Instrumentation的newActivity方法如下:

 public Activity newActivity(ClassLoader cl, String className,Intent intent)throws InstantiationException, IllegalAccessException,ClassNotFoundException {String pkg = intent != null && intent.getComponent() != null? intent.getComponent().getPackageName() : null;return getFactory(pkg).instantiateActivity(cl, className, intent);}private AppComponentFactory getFactory(String pkg) {if (pkg == null) {Log.e(TAG, "No pkg specified, disabling AppComponentFactory");return AppComponentFactory.DEFAULT;}if (mThread == null) {Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"+ " disabling AppComponentFactory", new Throwable());return AppComponentFactory.DEFAULT;}LoadedApk apk = mThread.peekPackageInfo(pkg, true);// This is in the case of starting up "android".if (apk == null) apk = mThread.getSystemContext().mPackageInfo;return apk.getAppFactory();}

通过代码可知:通过getFactory(pkg)方法得到的是AppComponentFactory对象,进入AppComponentFactory.java里面查看instantiateActivity方法

    public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,@Nullable Intent intent)throws InstantiationException, IllegalAccessException, ClassNotFoundException {return (Activity) cl.loadClass(className).newInstance();}

所以送上面代码可以知道在ActivityThread的performLaunchActivity 方法里面Instrumentation通过newActivity实例化了Activity,接着调用了Activity的attach方法。

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)final void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config, String referrer, IVoiceInteractor voiceInteractor,Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,IBinder shareableActivityToken) {attachBaseContext(context);mFragments.attachHost(null /*parent*/);//实例化PhoneWindow,Activity中持有PhoneWindowmWindow = new PhoneWindow(this, window, activityConfigCallback);mWindow.setWindowControllerCallback(mWindowControllerCallback);//将Activity自身设置到PhoneWindowmWindow.setCallback(this);mWindow.setOnWindowDismissedCallback(this);mWindow.getLayoutInflater().setPrivateFactory(this);if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {mWindow.setSoftInputMode(info.softInputMode);}if (info.uiOptions != 0) {mWindow.setUiOptions(info.uiOptions);}mUiThread = Thread.currentThread();mMainThread = aThread;mInstrumentation = instr;mToken = token;mAssistToken = assistToken;mShareableActivityToken = shareableActivityToken;mIdent = ident;mApplication = application;mIntent = intent;mReferrer = referrer;mComponent = intent.getComponent();mActivityInfo = info;mTitle = title;mParent = parent;mEmbeddedID = id;mLastNonConfigurationInstances = lastNonConfigurationInstances;if (voiceInteractor != null) {if (lastNonConfigurationInstances != null) {mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;} else {mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,Looper.myLooper());}}//将PhoneWindow关联到WindowManagermWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),mToken, mComponent.flattenToString(),(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);if (mParent != null) {mWindow.setContainer(mParent.getWindow());}//在Activity中持有windowManagermWindowManager = mWindow.getWindowManager();mCurrentConfig = config;mWindow.setColorMode(info.colorMode);mWindow.setPreferMinimalPostProcessing((info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) != 0);setAutofillOptions(application.getAutofillOptions());setContentCaptureOptions(application.getContentCaptureOptions());}

调用了attach方法之后,接着通过Instrumentation执行了Activity的callActivityOnCreate方法,代码如下:

  public void callActivityOnCreate(Activity activity, Bundle icicle,PersistableBundle persistentState) {prePerformCreate(activity);activity.performCreate(icicle, persistentState);postPerformCreate(activity);}

在Activity的callActivityOnCreate方法中最终会调用到Activity的onCreate方法。

onStart方法的执行

在前面我们分析了Activity后会执行oncreate,onStart,onResume方法这些生命周期方法。onStart是通过ActivityThread的handleStartActivity来执行的。其源码如下:

  @Overridepublic void handleStartActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, ActivityOptions activityOptions) {final Activity activity = r.activity;if (!r.stopped) {throw new IllegalStateException("Can't start activity that is not stopped.");}if (r.activity.mFinished) {// TODO(lifecycler): How can this happen?return;}unscheduleGcIdler();if (activityOptions != null) {activity.mPendingOptions = activityOptions;}// Start//调用Activity的performStart进而执行onStartactivity.performStart("handleStartActivity");//将生命周期状态设置为on_startr.setState(ON_START);if (pendingActions == null) {// No more work to do.return;}// Restore instance stateif (pendingActions.shouldRestoreInstanceState()) {if (r.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);}}// Call postOnCreate()if (pendingActions.shouldCallOnPostCreate()) {activity.mCalled = false;if (r.isPersistable()) {mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnPostCreate(activity, r.state);}if (!activity.mCalled) {throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString()+ " did not call through to super.onPostCreate()");}}updateVisibility(r, true /* show */);mSomeActivitiesChanged = true;}

handleStartActivity的逻辑比较简单,就是调用了Activity的performStart方法,进而调用了onStart方法。

onResume 方法的调用

onResume方法是通过ActivityThread的handleResumeActivity来执行的。
源码如下:

   @Overridepublic void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, String reason) {// If we are getting ready to gc after going to the background, well// we are back active so skip it.unscheduleGcIdler();mSomeActivitiesChanged = true;// TODO Push resumeArgs into the activity for consideration// skip below steps for double-resume and r.mFinish = true case.if (!performResumeActivity(r, finalStateRequest, reason)) {return;}if (mActivitiesToBeDestroyed.containsKey(r.token)) {// Although the activity is resumed, it is going to be destroyed. So the following// UI operations are unnecessary and also prevents exception because its token may// be gone that window manager cannot recognize it. All necessary cleanup actions// performed below will be done while handling destruction.return;}final Activity a = r.activity;if (localLOGV) {Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity+ ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);}final int forwardBit = isForward? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;// If the window hasn't yet been added to the window manager,// and this guy didn't finish itself or start another activity,// then go ahead and add the window.boolean willBeVisible = !a.mStartedActivity;if (!willBeVisible) {willBeVisible = ActivityClient.getInstance().willActivityBeVisible(a.getActivityToken());}if (r.window == null && !a.mFinished && willBeVisible) {//获取PhoneWindowr.window = r.activity.getWindow();//获取DecorViewView decor = r.window.getDecorView();//设置DecorView不可见decor.setVisibility(View.INVISIBLE);//获取WindowManagerViewManager wm = a.getWindowManager();//获取window的属性参数WindowManager.LayoutParams l = r.window.getAttributes();a.mDecor = decor;l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;l.softInputMode |= forwardBit;if (r.mPreserveWindow) {a.mWindowAdded = true;r.mPreserveWindow = false;// Normally the ViewRoot sets up callbacks with the Activity// in addView->ViewRootImpl#setView. If we are instead reusing// the decor view we have to notify the view root that the// callbacks may have changed.ViewRootImpl impl = decor.getViewRootImpl();if (impl != null) {impl.notifyChildRebuilt();}}if (a.mVisibleFromClient) {if (!a.mWindowAdded) {a.mWindowAdded = true;//通过WindowManager将DecorView添加到窗口wm.addView(decor, l);} else {// The activity will get a callback for this {@link LayoutParams} change// earlier. However, at that time the decor will not be set (this is set// in this method), so no action will be taken. This call ensures the// callback occurs with the decor set.a.onWindowAttributesChanged(l);}}// If the window has already been added, but during resume// we started another activity, then don't yet make the// window visible.} else if (!willBeVisible) {if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");r.hideForNow = true;}// Get rid of anything left hanging around.cleanUpPendingRemoveWindows(r, false /* force */);// The window is now visible if it has been added, we are not// simply finishing, and we are not starting another activity.if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);ViewRootImpl impl = r.window.getDecorView().getViewRootImpl();WindowManager.LayoutParams l = impl != null? impl.mWindowAttributes : r.window.getAttributes();if ((l.softInputMode& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)!= forwardBit) {l.softInputMode = (l.softInputMode& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))| forwardBit;if (r.activity.mVisibleFromClient) {ViewManager wm = a.getWindowManager();View decor = r.window.getDecorView();wm.updateViewLayout(decor, l);}}r.activity.mVisibleFromServer = true;mNumVisibleActivities++;if (r.activity.mVisibleFromClient) {r.activity.makeVisible();}}r.nextIdle = mNewActivities;mNewActivities = r;if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);Looper.myQueue().addIdleHandler(new Idler());}

handleResumeActivity方法中的逻辑比较复杂,但核心主要有两点:
1、调用performResumeActivity执行onResume的生命周期
2、将DecorView添加到Window中。
先来看performResumeActivity方法其源码如下:

    @VisibleForTestingpublic boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,String reason) {if (localLOGV) {Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);}if (r.activity.mFinished) {//如果activity已经finish状态,直接return falsereturn false;}if (r.getLifecycleState() == ON_RESUME) {if (!finalStateRequest) {final RuntimeException e = new IllegalStateException("Trying to resume activity which is already resumed");Slog.e(TAG, e.getMessage(), e);Slog.e(TAG, r.getStateString());// TODO(lifecycler): A double resume request is possible when an activity// receives two consequent transactions with relaunch requests and "resumed"// final state requests and the second relaunch is omitted. We still try to// handle two resume requests for the final state. For cases other than this// one, we don't expect it to happen.}//如果已经是resume状态直接return false,避免重复执行return false;}if (finalStateRequest) {r.hideForNow = false;r.activity.mStartedActivity = false;}try {r.activity.onStateNotSaved();r.activity.mFragments.noteStateNotSaved();checkAndBlockForNetworkAccess();if (r.pendingIntents != null) {deliverNewIntents(r, r.pendingIntents);r.pendingIntents = null;}if (r.pendingResults != null) {deliverResults(r, r.pendingResults, reason);r.pendingResults = null;}//执行activity的performResume进而执行onResumer.activity.performResume(r.startsNotResumed, reason);r.state = null;r.persistentState = null;//设置Activity的状态为ON_RESUMEr.setState(ON_RESUME);reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming");} catch (Exception e) {if (!mInstrumentation.onException(r.activity, e)) {throw new RuntimeException("Unable to resume activity "+ r.intent.getComponent().toShortString() + ": " + e.toString(), e);}}return true;}

在performResumeActivity中先对Activity的状态进行了判断,如果符合状态,则会调用Activity的performResume方法,进而执行Activity的onResume。
在完成了performResume的调用后,performResumeActivity方法中接着执行了将DecorView添加到Window的过程,代码如上所示,可以看到核心就是wm.addView(decor,1)这行代码,通过ViewManager的addView方法将DecorView添加到了窗口中。窗口的添加过程会完成DecorView的布局、测量与绘制。当完成窗口的添加后Activity的View才被显示出来,且有了宽度。

四、根Activity的启动

根应用进程的创建

在第二节中讲到ActivityStackSupervisor.startSpecificActivity()启动会判断进程是否存在,如果不存在则创建进程。我们下面就根据这个逻辑来分信息,如果进程不存在会调用mService.startProcessAsync()方法,具体代码如下:

void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,String hostingType) {try {if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"+ activity.processName);}// Post message to start process to avoid possible deadlock of calling into AMS with the// ATMS lock held.//发布消息以启动进程,以避免在持有ATMS锁的情况下调用AMS可能出现的死锁final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,isTop, hostingType, activity.intent.getComponent());mH.sendMessage(m);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}

使用ActivityTaskManagerService的mH(继承handler)发送了一个消息,消息中第一个此参数是ActivityManagerInternal::startProcess,ActivityManagerInternal的实现是AMS的内部类LocalServvice,LocalService的startProcess方法调用了AMS的startProcessLocked方法,那么我们就看AMS的startProcessLocked方法,这里应该就是创建进程了:

 @GuardedBy("this")final ProcessRecord startProcessLocked(String processName,ApplicationInfo info, boolean knownToBeDead, int intentFlags,HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,boolean isolated) {return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,null /* ABI override */, null /* entryPoint */,null /* entryPointArgs */, null /* crashHandler */);}

这里调用了ProcessList.startProcessLocked方法,内部又多次调用了startProcessLocked不同的重载方法,最后走到startProcess方法

    private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,int mountExternal, String seInfo, String requiredAbi, String instructionSet,String invokeWith, long startTime) {try {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +app.processName);checkSlow(startTime, "startProcess: asking zygote to start proc");final boolean isTopApp = hostingRecord.isTopApp();if (isTopApp) {// Use has-foreground-activities as a temporary hint so the current scheduling// group won't be lost when the process is attaching. The actual state will be// refreshed when computing oom-adj.app.mState.setHasForegroundActivities(true);}Map<String, Pair<String, Long>> pkgDataInfoMap;Map<String, Pair<String, Long>> allowlistedAppDataInfoMap;boolean bindMountAppStorageDirs = false;boolean bindMountAppsData = mAppDataIsolationEnabled&& (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid))&& mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);// Get all packages belongs to the same shared uid. sharedPackages is empty array// if it doesn't have shared uid.final PackageManagerInternal pmInt = mService.getPackageManagerInternal();final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(app.info.packageName, app.userId);final String[] targetPackagesList = sharedPackages.length == 0? new String[]{app.info.packageName} : sharedPackages;pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);if (pkgDataInfoMap == null) {// TODO(b/152760674): Handle inode == 0 case properly, now we just give it a// tmp free pass.bindMountAppsData = false;}// Remove all packages in pkgDataInfoMap from mAppDataIsolationAllowlistedApps, so// it won't be mounted twice.final Set<String> allowlistedApps = new ArraySet<>(mAppDataIsolationAllowlistedApps);for (String pkg : targetPackagesList) {allowlistedApps.remove(pkg);}allowlistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,allowlistedApps.toArray(new String[0]), uid);if (allowlistedAppDataInfoMap == null) {// TODO(b/152760674): Handle inode == 0 case properly, now we just give it a// tmp free pass.bindMountAppsData = false;}int userId = UserHandle.getUserId(uid);StorageManagerInternal storageManagerInternal = LocalServices.getService(StorageManagerInternal.class);if (needsStorageDataIsolation(storageManagerInternal, app)) {// We will run prepareStorageDirs() after we trigger zygote fork, so it won't// slow down app starting speed as those dirs might not be cached.if (pkgDataInfoMap != null && storageManagerInternal.isFuseMounted(userId)) {bindMountAppStorageDirs = true;} else {// Fuse is not mounted or inode == 0,// so we won't mount it in zygote, but resume the mount after unlocking device.app.setBindMountPending(true);bindMountAppStorageDirs = false;}}// If it's an isolated process, it should not even mount its own app data directories,// since it has no access to them anyway.if (app.isolated) {pkgDataInfoMap = null;allowlistedAppDataInfoMap = null;}final Process.ProcessStartResult startResult;boolean regularZygote = false;if (hostingRecord.usesWebviewZygote()) {startResult = startWebView(entryPoint,app.processName, uid, uid, gids, runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, null, app.info.packageName,app.getDisabledCompatChanges(),new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});} else if (hostingRecord.usesAppZygote()) {final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);// We can't isolate app data and storage data as parent zygote already did that.startResult = appZygote.getProcess().start(entryPoint,app.processName, uid, uid, gids, runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, null, app.info.packageName,/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap,false, false,new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});} else {regularZygote = true;startResult = Process.start(entryPoint,app.processName, uid, uid, gids, runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});}if (!regularZygote) {// webview and app zygote don't have the permission to create the nodesif (Process.createProcessGroup(uid, startResult.pid) < 0) {Slog.e(ActivityManagerService.TAG, "Unable to create process group for "+ app.processName + " (" + startResult.pid + ")");}}// This runs after Process.start() as this method may block app process starting time// if dir is not cached. Running this method after Process.start() can make it// cache the dir asynchronously, so zygote can use it without waiting for it.if (bindMountAppStorageDirs) {storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),app.processName);}checkSlow(startTime, "startProcess: returned from zygote!");return startResult;} finally {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}}

调用了Process.start方法,代码如下:

    public static ProcessStartResult start(@NonNull final String processClass,@Nullable final String niceName,int uid, int gid, @Nullable int[] gids,int runtimeFlags,int mountExternal,int targetSdkVersion,@Nullable String seInfo,@NonNull String abi,@Nullable String instructionSet,@Nullable String appDataDir,@Nullable String invokeWith,@Nullable String packageName,int zygotePolicyFlags,boolean isTopApp,@Nullable long[] disabledCompatChanges,@Nullable Map<String, Pair<String, Long>>pkgDataInfoMap,@Nullable Map<String, Pair<String, Long>>whitelistedDataInfoMap,boolean bindMountAppsData,boolean bindMountAppStorageDirs,@Nullable String[] zygoteArgs) {return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,runtimeFlags, mountExternal, targetSdkVersion, seInfo,abi, instructionSet, appDataDir, invokeWith, packageName,zygotePolicyFlags, isTopApp, disabledCompatChanges,pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,bindMountAppStorageDirs, zygoteArgs);}

ZYGOTE_PROCESS是用于保持与Zygote进程的通信状态,发送socket请求与Zygote进程通信。我们知道其内部主要做了1、Zygote通过fork创建了一个新的进程,2、在新建的进程中创建Binder线程池。3、通过反射获取了ActivityThread类并执行了main方法

根Activity的启动

ActivityThread的main方法。具体代码如下:

 public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// Install selective syscall interception//安全选择性的系统调用拦截AndroidOs.install();// CloseGuard defaults to true and can be quite spammy. We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);// Call per-process mainline module initialization.initializeMainlineModules();Process.setArgV0("<pre-initialized>");//1、创建MainLooperLooper.prepareMainLooper();// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.// It will be in the format "seq=114"long startSeq = 0;if (args != null) {for (int i = args.length - 1; i >= 0; --i) {if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {startSeq = Long.parseLong(args[i].substring(PROC_START_SEQ_IDENT.length()));}}}//之前SystemServer调用attach传入的是true,这里到应用进程传入false就行//2、创建ActivityThreadActivityThread thread = new ActivityThread();//3、调用attach方法thread.attach(false, startSeq);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);//一直循环,保障程序一直执行,如果退出,说明程序关闭Looper.loop();//因为主线程的Looper是不能退出的,退出就无法接收事件了,一旦意外退出,就会抛出异常throw new RuntimeException("Main thread loop unexpectedly exited");}

在main方法里面主要做了三件事:1、创建mainLooper,2、创建ActivityThread实例3、调用了attach方法。创建ActivityThread实例,同时会创建ApplicationThread实例,ApplicationThread实例是ActivityThread实例的属性。然后调用了attach方法:

    @UnsupportedAppUsageprivate void attach(boolean system, long startSeq) {sCurrentActivityThread = this;mConfigurationController = new ConfigurationController(this);mSystemThread = system;//传递过来的system参数是true,startSeq =0//ActivityThread.main方法传递过来的system参数为falseif (!system) {android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",UserHandle.myUserId());RuntimeInit.setApplicationObject(mAppThread.asBinder());//获取AMS的本地代理类final IActivityManager mgr = ActivityManager.getService();try {//通过Binder调用AMS的attachApplication方法把ApplicationThread实例关联到AMS中mgr.attachApplication(mAppThread, startSeq);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}// Watch for getting close to heap limit.BinderInternal.addGcWatcher(new Runnable() {@Override public void run() {if (!mSomeActivitiesChanged) {return;}Runtime runtime = Runtime.getRuntime();long dalvikMax = runtime.maxMemory();long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();if (dalvikUsed > ((3*dalvikMax)/4)) {if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)+ " total=" + (runtime.totalMemory()/1024)+ " used=" + (dalvikUsed/1024));mSomeActivitiesChanged = false;try {ActivityTaskManager.getService().releaseSomeActivities(mAppThread);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}}});} else {// Don't set application object here -- if the system crashes,// we can't display an alert, we just want to die die die.android.ddm.DdmHandleAppName.setAppName("system_process",UserHandle.myUserId());try {//创建了ContextImpl还执行了application的onCreate方法mInstrumentation = new Instrumentation();mInstrumentation.basicInit(this);ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);mInitialApplication = context.mPackageInfo.makeApplication(true, null);mInitialApplication.onCreate();} catch (Exception e) {throw new RuntimeException("Unable to instantiate Application():" + e.toString(), e);}}//为ViewRootImpl设置配置更新回调//当系统资源配置(如:系统字体)发生变化时,通知系统配置发生变化ViewRootImpl.ConfigChangedCallback configChangedCallback = (Configuration globalConfig) -> {synchronized (mResourcesManager) {// We need to apply this change to the resources immediately, because upon returning// the view hierarchy will be informed about it.if (mResourcesManager.applyConfigurationToResources(globalConfig,null /* compat */,mInitialApplication.getResources().getDisplayAdjustments())) {mConfigurationController.updateLocaleListFromAppContext(mInitialApplication.getApplicationContext());// This actually changed the resources! Tell everyone about it.final Configuration updatedConfig =mConfigurationController.updatePendingConfiguration(globalConfig);if (updatedConfig != null) {sendMessage(H.CONFIGURATION_CHANGED, globalConfig);mPendingConfiguration = updatedConfig;}}}};ViewRootImpl.addConfigCallback(configChangedCallback);}

根据ActivityThread.main方法中传递过来的参数得知system参数为false,所以会执行(!system)里面的内容。可以看到获取AMS的本地代理类对象,然后调用attachApplication方法,就是IPC的走到AMS的attachApplication方法

 @Overridepublic final void attachApplication(IApplicationThread thread, long startSeq) {if (thread == null) {throw new SecurityException("Invalid application interface");}synchronized (this) {int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid, callingUid, startSeq);Binder.restoreCallingIdentity(origId);}}

在attachApplication方法中调用了attachApplicationLock()方法

	/***该方法主要做了两件事:1、调用ApplicationThread的bindApplication()方法去初始化Application,又是一次跨进程调用2、通过makeActive方法赋值IApplicationThread3、通过ATMS去启动目标Activity*/@GuardedBy("this")private boolean attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {// Find the application record that is being attached...  either via// the pid if we are running in multiple processes, or just pull the// next app record if we are emulating process with anonymous threads.ProcessRecord app;long startTime = SystemClock.uptimeMillis();long bindApplicationTimeMillis;if (pid != MY_PID && pid >= 0) {synchronized (mPidsSelfLocked) {app = mPidsSelfLocked.get(pid);}if (app != null && (app.getStartUid() != callingUid || app.getStartSeq() != startSeq)) {String processName = null;final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);if (pending != null) {processName = pending.processName;}final String msg = "attachApplicationLocked process:" + processName+ " startSeq:" + startSeq+ " pid:" + pid+ " belongs to another existing app:" + app.processName+ " startSeq:" + app.getStartSeq();Slog.wtf(TAG, msg);// SafetyNet logging for b/131105245.EventLog.writeEvent(0x534e4554, "131105245", app.getStartUid(), msg);// If there is already an app occupying that pid that hasn't been cleaned upcleanUpApplicationRecordLocked(app, pid, false, false, -1,true /*replacingPid*/, false /* fromBinderDied */);removePidLocked(pid, app);app = null;}} else {app = null;}// It's possible that process called attachApplication before we got a chance to// update the internal state.if (app == null && startSeq > 0) {final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);if (pending != null && pending.getStartUid() == callingUid&& pending.getStartSeq() == startSeq&& mProcessList.handleProcessStartedLocked(pending, pid,pending.isUsingWrapper(), startSeq, true)) {app = pending;}}if (app == null) {Slog.w(TAG, "No pending application record for pid " + pid+ " (IApplicationThread " + thread + "); dropping process");EventLogTags.writeAmDropProcess(pid);if (pid > 0 && pid != MY_PID) {killProcessQuiet(pid);//TODO: killProcessGroup(app.info.uid, pid);// We can't log the app kill info for this process since we don't// know who it is, so just skip the logging.} else {try {thread.scheduleExit();} catch (Exception e) {// Ignore exceptions.}}return false;}// If this application record is still attached to a previous// process, clean it up now.if (app.getThread() != null) {handleAppDiedLocked(app, pid, true, true, false /* fromBinderDied */);}// Tell the process all about itself.if (DEBUG_ALL) Slog.v(TAG, "Binding process pid " + pid + " to record " + app);final String processName = app.processName;try {AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);thread.asBinder().linkToDeath(adr, 0);app.setDeathRecipient(adr);} catch (RemoteException e) {app.resetPackageList(mProcessStats);mProcessList.startProcessLocked(app,new HostingRecord("link fail", processName),ZYGOTE_POLICY_FLAG_EMPTY);return false;}EventLogTags.writeAmProcBound(app.userId, pid, app.processName);synchronized (mProcLock) {app.mState.setCurAdj(ProcessList.INVALID_ADJ);app.mState.setSetAdj(ProcessList.INVALID_ADJ);app.mState.setVerifiedAdj(ProcessList.INVALID_ADJ);mOomAdjuster.setAttachingSchedGroupLSP(app);app.mState.setForcingToImportant(null);updateProcessForegroundLocked(app, false, 0, false);app.mState.setHasShownUi(false);app.mState.setCached(false);app.setDebugging(false);app.setKilledByAm(false);app.setKilled(false);// We carefully use the same state that PackageManager uses for// filtering, since we use this flag to decide if we need to install// providers when user is unlocked laterapp.setUnlocked(StorageManager.isUserKeyUnlocked(app.userId));}mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);List<ProviderInfo> providers = normalMode? mCpHelper.generateApplicationProvidersLocked(app): null;if (providers != null && mCpHelper.checkAppInLaunchingProvidersLocked(app)) {Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);msg.obj = app;mHandler.sendMessageDelayed(msg,ContentResolver.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS);}checkTime(startTime, "attachApplicationLocked: before bindApplication");if (!normalMode) {Slog.i(TAG, "Launching preboot mode app: " + app);}if (DEBUG_ALL) Slog.v(TAG, "New app record " + app+ " thread=" + thread.asBinder() + " pid=" + pid);final BackupRecord backupTarget = mBackupTargets.get(app.userId);try {int testMode = ApplicationThreadConstants.DEBUG_OFF;if (mDebugApp != null && mDebugApp.equals(processName)) {testMode = mWaitForDebugger? ApplicationThreadConstants.DEBUG_WAIT: ApplicationThreadConstants.DEBUG_ON;app.setDebugging(true);if (mDebugTransient) {mDebugApp = mOrigDebugApp;mWaitForDebugger = mOrigWaitForDebugger;}}boolean enableTrackAllocation = false;synchronized (mProcLock) {if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {enableTrackAllocation = true;mTrackAllocationApp = null;}}// If the app is being launched for restore or full backup, set it up speciallyboolean isRestrictedBackupMode = false;if (backupTarget != null && backupTarget.appInfo.packageName.equals(processName)) {isRestrictedBackupMode = backupTarget.appInfo.uid >= FIRST_APPLICATION_UID&& ((backupTarget.backupMode == BackupRecord.RESTORE)|| (backupTarget.backupMode == BackupRecord.RESTORE_FULL)|| (backupTarget.backupMode == BackupRecord.BACKUP_FULL));}final ActiveInstrumentation instr = app.getActiveInstrumentation();if (instr != null) {notifyPackageUse(instr.mClass.getPackageName(),PackageManager.NOTIFY_PACKAGE_USE_INSTRUMENTATION);}ProtoLog.v(WM_DEBUG_CONFIGURATION, "Binding proc %s with config %s",processName, app.getWindowProcessController().getConfiguration());ApplicationInfo appInfo = instr != null ? instr.mTargetInfo : app.info;app.setCompat(compatibilityInfoForPackage(appInfo));ProfilerInfo profilerInfo = mAppProfiler.setupProfilerInfoLocked(thread, app, instr);// We deprecated Build.SERIAL and it is not accessible to// Instant Apps and target APIs higher than O MR1. Since access to the serial// is now behind a permission we push down the value.final String buildSerial = (!appInfo.isInstantApp()&& appInfo.targetSdkVersion < Build.VERSION_CODES.P)? sTheRealBuildSerial : Build.UNKNOWN;// Figure out whether the app needs to run in autofill compat mode.AutofillOptions autofillOptions = null;if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) {final AutofillManagerInternal afm = LocalServices.getService(AutofillManagerInternal.class);if (afm != null) {autofillOptions = afm.getAutofillOptions(app.info.packageName, app.info.longVersionCode, app.userId);}}ContentCaptureOptions contentCaptureOptions = null;if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) {final ContentCaptureManagerInternal ccm =LocalServices.getService(ContentCaptureManagerInternal.class);if (ccm != null) {contentCaptureOptions = ccm.getOptionsForPackage(app.userId,app.info.packageName);}}SharedMemory serializedSystemFontMap = null;final FontManagerInternal fm = LocalServices.getService(FontManagerInternal.class);if (fm != null) {serializedSystemFontMap = fm.getSerializedSystemFontMap();}checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");bindApplicationTimeMillis = SystemClock.elapsedRealtime();mAtmInternal.preBindApplication(app.getWindowProcessController());final ActiveInstrumentation instr2 = app.getActiveInstrumentation();if (mPlatformCompat != null) {mPlatformCompat.resetReporting(app.info);}final ProviderInfoList providerList = ProviderInfoList.fromList(providers);if (app.getIsolatedEntryPoint() != null) {// This is an isolated process which should just call an entry point instead of// being bound to an application.thread.runIsolatedEntryPoint(app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());} else if (instr2 != null) {//IPC操作,调用ApplicationThread的bindapplication去初始化Applicationthread.bindApplication(processName, appInfo, providerList,instr2.mClass,profilerInfo, instr2.mArguments,instr2.mWatcher,instr2.mUiAutomationConnection, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()),app.getCompat(), getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions,app.getDisabledCompatChanges(), serializedSystemFontMap);} else {thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,null, null, null, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()),app.getCompat(), getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions,app.getDisabledCompatChanges(), serializedSystemFontMap);}if (profilerInfo != null) {profilerInfo.closeFd();profilerInfo = null;}// Make app active after binding application or client may be running requests (e.g// starting activities) before it is ready.synchronized (mProcLock) {//赋值IApplicationThreadapp.makeActive(thread, mProcessStats);checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");}updateLruProcessLocked(app, false, null);checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");final long now = SystemClock.uptimeMillis();synchronized (mAppProfiler.mProfilerLock) {app.mProfile.setLastRequestedGc(now);app.mProfile.setLastLowMemory(now);}} catch (Exception e) {// We need kill the process group here. (b/148588589)Slog.wtf(TAG, "Exception thrown during bind of " + app, e);app.resetPackageList(mProcessStats);app.unlinkDeathRecipient();app.killLocked("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,true);handleAppDiedLocked(app, pid, false, true, false /* fromBinderDied */);return false;}// Remove this record from the list of starting applications.mPersistentStartingProcesses.remove(app);if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,"Attach application locked removing on hold: " + app);mProcessesOnHold.remove(app);boolean badApp = false;boolean didSomething = false;// See if the top visible activity is waiting to run in this process...if (normalMode) {try {//通过ATMS去启动ActivitydidSomething = mAtmInternal.attachApplication(app.getWindowProcessController());} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}// Find any services that should be running in this process...if (!badApp) {try {didSomething |= mServices.attachApplicationLocked(app, processName);checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");} catch (Exception e) {Slog.wtf(TAG, "Exception thrown starting services in " + app, e);badApp = true;}}// Check if a next-broadcast receiver is in this process...if (!badApp && isPendingBroadcastProcessLocked(pid)) {try {didSomething |= sendPendingBroadcastsLocked(app);checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");} catch (Exception e) {// If the app died trying to launch the receiver we declare it 'bad'Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);badApp = true;}}// Check whether the next backup agent is in this process...if (!badApp && backupTarget != null && backupTarget.app == app) {if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,"New app is backup target, launching agent for " + app);notifyPackageUse(backupTarget.appInfo.packageName,PackageManager.NOTIFY_PACKAGE_USE_BACKUP);try {thread.scheduleCreateBackupAgent(backupTarget.appInfo,compatibilityInfoForPackage(backupTarget.appInfo),backupTarget.backupMode, backupTarget.userId, backupTarget.operationType);} catch (Exception e) {Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);badApp = true;}}if (badApp) {app.killLocked("error during init", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,true);handleAppDiedLocked(app, pid, false, true, false /* fromBinderDied */);return false;}if (!didSomething) {updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");}FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_START_TIME,app.info.uid,pid,app.info.packageName,FrameworkStatsLog.PROCESS_START_TIME__TYPE__COLD,app.getStartTime(),(int) (bindApplicationTimeMillis - app.getStartTime()),(int) (SystemClock.elapsedRealtime() - app.getStartTime()),app.getHostingRecord().getType(),(app.getHostingRecord().getName() != null ? app.getHostingRecord().getName() : ""));return true;}

在attachApplicationLocked方法中主要做了三件事:
1、调用IApplicationThread的bindApplication方法,IPC操作,创建绑定Application
2、通过makeActive方法赋值IApplicationThread
3、通过ATMS启动根Activity
先看makeActive方法:

    @GuardedBy({"mService", "mProcLock"})public void makeActive(IApplicationThread thread, ProcessStatsService tracker) {mProfile.onProcessActive(thread, tracker);mThread = thread;mWindowProcessController.setThread(thread);}

可以看到使用 mWindowProcessController.setThread(thread)确实完成了IApplicationThread的赋值。这样就可以依据IApplicationThread是否为空判断进程是否存在。
再看创建绑定Application的过程:IApplicationThread的bindApplication方法实现客户端ApplicationThread的bindApplication方法,它有使用H转移到了ActivityThread的handleBindApplication方法。

	/*该函数主要做了三件事1、创建Instrumentation2、使用loadedApk创建一个application,不过最终还是使用的Instrumentation利用反射创建的Application类3、使用Instrumentation初始化Application**/@UnsupportedAppUsageprivate void handleBindApplication(AppBindData data) {// Register the UI Thread as a sensitive thread to the runtime.VMRuntime.registerSensitiveThread();// In the case the stack depth property exists, pass it down to the runtime.String property = SystemProperties.get("debug.allocTracker.stackDepth");if (property.length() != 0) {VMDebug.setAllocTrackerStackDepth(Integer.parseInt(property));}if (data.trackAllocation) {DdmVmInternal.setRecentAllocationsTrackingEnabled(true);}// Note when this process has started.Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());AppCompatCallbacks.install(data.disabledCompatChanges);// Let libcore handle any compat changes after installing the list of compat changes.AppSpecializationHooks.handleCompatChangesBeforeBindingApplication();mBoundApplication = data;mConfigurationController.setConfiguration(data.config);mConfigurationController.setCompatConfiguration(data.config);mConfiguration = mConfigurationController.getConfiguration();mProfiler = new Profiler();String agent = null;if (data.initProfilerInfo != null) {mProfiler.profileFile = data.initProfilerInfo.profileFile;mProfiler.profileFd = data.initProfilerInfo.profileFd;mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;if (data.initProfilerInfo.attachAgentDuringBind) {agent = data.initProfilerInfo.agent;}}// send up app name; do this *before* waiting for debugger//发送应用程序名称;在等待调试器之前执行此操作Process.setArgV0(data.processName);android.ddm.DdmHandleAppName.setAppName(data.processName,data.appInfo.packageName,UserHandle.myUserId());VMRuntime.setProcessPackageName(data.appInfo.packageName);// Pass data directory path to ART. This is used for caching information and// should be set before any application code is loaded.VMRuntime.setProcessDataDirectory(data.appInfo.dataDir);if (mProfiler.profileFd != null) {mProfiler.startProfiling();}// If the app is Honeycomb MR1 or earlier, switch its AsyncTask// implementation to use the pool executor. Normally, we use the// serialized executor as the default. This has to happen in the// main thread so the main looper is set right.if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);}// Let the util.*Array classes maintain "undefined" for apps targeting Pie or earlier.UtilConfig.setThrowExceptionForUpperArrayOutOfBounds(data.appInfo.targetSdkVersion >= Build.VERSION_CODES.Q);Message.updateCheckRecycle(data.appInfo.targetSdkVersion);// Supply the targetSdkVersion to the UI rendering module, which may// need it in cases where it does not have access to the appInfo.android.graphics.Compatibility.setTargetSdkVersion(data.appInfo.targetSdkVersion);/** Before spawning a new process, reset the time zone to be the system time zone.* This needs to be done because the system time zone could have changed after the* the spawning of this process. Without doing this this process would have the incorrect* system time zone.*/TimeZone.setDefault(null);/** Set the LocaleList. This may change once we create the App Context.*/LocaleList.setDefault(data.config.getLocales());if (Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) {try {Typeface.setSystemFontMap(data.mSerializedSystemFontMap);} catch (IOException | ErrnoException e) {Slog.e(TAG, "Failed to parse serialized system font map");Typeface.loadPreinstalledSystemFontMap();}}synchronized (mResourcesManager) {/** Update the system configuration since its preloaded and might not* reflect configuration changes. The configuration object passed* in AppBindData can be safely assumed to be up to date*/mResourcesManager.applyConfigurationToResources(data.config, data.compatInfo);mCurDefaultDisplayDpi = data.config.densityDpi;// This calls mResourcesManager so keep it within the synchronized block.mConfigurationController.applyCompatConfiguration();}data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);if (agent != null) {handleAttachAgent(agent, data.info);}/*** Switch this process to density compatibility mode if needed.*/if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)== 0) {mDensityCompatMode = true;Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);}mConfigurationController.updateDefaultDensity(data.config.densityDpi);// mCoreSettings is only updated from the main thread, while this function is only called// from main thread as well, so no need to lock here.final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24);Boolean is24Hr = null;if (use24HourSetting != null) {is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE;}// null : use locale default for 12/24 hour formatting,// false : use 12 hour format,// true : use 24 hour format.DateFormat.set24HourTimePref(is24Hr);updateDebugViewAttributeState();StrictMode.initThreadDefaults(data.appInfo);StrictMode.initVmDefaults(data.appInfo);if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {// XXX should have option to change the port.Debug.changeDebugPort(8100);if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {Slog.w(TAG, "Application " + data.info.getPackageName()+ " is waiting for the debugger on port 8100...");IActivityManager mgr = ActivityManager.getService();try {mgr.showWaitingForDebugger(mAppThread, true);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}Debug.waitForDebugger();try {mgr.showWaitingForDebugger(mAppThread, false);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}} else {Slog.w(TAG, "Application " + data.info.getPackageName()+ " can be debugged on port 8100...");}}// Allow binder tracing, and application-generated systrace messages if we're profileable.boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;boolean isAppProfileable = isAppDebuggable || data.appInfo.isProfileable();Trace.setAppTracingAllowed(isAppProfileable);if ((isAppProfileable || Build.IS_DEBUGGABLE) && data.enableBinderTracking) {Binder.enableTracing();}// Initialize heap profiling.if (isAppProfileable || Build.IS_DEBUGGABLE) {nInitZygoteChildHeapProfiling();}// Allow renderer debugging features if we're debuggable.HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);HardwareRenderer.setPackageName(data.appInfo.packageName);// Pass the current context to HardwareRendererHardwareRenderer.setContextForInit(getSystemContext());// Instrumentation info affects the class loader, so load it before// setting up the app context.final InstrumentationInfo ii;if (data.instrumentationName != null) {ii = prepareInstrumentation(data);} else {ii = null;}final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);mConfigurationController.updateLocaleListFromAppContext(appContext);// Initialize the default http proxy in this process.Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies");try {// In pre-boot mode (doing initial launch to collect password), not all system is up.// This includes the connectivity service, so trying to obtain ConnectivityManager at// that point would return null. Check whether the ConnectivityService is available, and// avoid crashing with a NullPointerException if it is not.final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);if (b != null) {final ConnectivityManager cm =appContext.getSystemService(ConnectivityManager.class);Proxy.setHttpProxyConfiguration(cm.getDefaultProxy());}} finally {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}if (!Process.isIsolated()) {final int oldMask = StrictMode.allowThreadDiskWritesMask();try {setupGraphicsSupport(appContext);} finally {StrictMode.setThreadPolicyMask(oldMask);}} else {HardwareRenderer.setIsolatedProcess(true);}// Install the Network Security Config Provider. This must happen before the application// code is loaded to prevent issues with instances of TLS objects being created before// the provider is installed.Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "NetworkSecurityConfigProvider.install");NetworkSecurityConfigProvider.install(appContext);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);// Continue loading instrumentation.if (ii != null) {initInstrumentation(ii, data, appContext);} else {mInstrumentation = new Instrumentation();mInstrumentation.basicInit(this);}if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();} else {// Small heap, clamp to the current growth limit and let the heap release// pages after the growth limit to the non growth limit capacity. b/18387825dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();}// Allow disk access during application and provider setup. This could// block processing ordered broadcasts, but later processing would// probably end up doing the same disk access.Application app;final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();try {// If the app is being launched for full backup or restore, bring it up in// a restricted environment with the base application class.//创建applicationapp = data.info.makeApplication(data.restrictedBackupMode, null);// Propagate autofill compat stateapp.setAutofillOptions(data.autofillOptions);// Propagate Content Capture optionsapp.setContentCaptureOptions(data.contentCaptureOptions);sendMessage(H.SET_CONTENT_CAPTURE_OPTIONS_CALLBACK, data.appInfo.packageName);mInitialApplication = app;final boolean updateHttpProxy;synchronized (this) {updateHttpProxy = mUpdateHttpProxyOnBind;// This synchronized block ensures that any subsequent call to updateHttpProxy()// will see a non-null mInitialApplication.}if (updateHttpProxy) {ActivityThread.updateHttpProxy(app);}// don't bring up providers in restricted mode; they may depend on the// app's custom Application classif (!data.restrictedBackupMode) {if (!ArrayUtils.isEmpty(data.providers)) {installContentProviders(app, data.providers);}}// Do this after providers, since instrumentation tests generally start their// test thread at this point, and we don't want that racing.try {mInstrumentation.onCreate(data.instrumentationArgs);} catch (Exception e) {throw new RuntimeException("Exception thrown in onCreate() of "+ data.instrumentationName + ": " + e.toString(), e);}try {//调用application的onCreate方法mInstrumentation.callApplicationOnCreate(app);} catch (Exception e) {if (!mInstrumentation.onException(app, e)) {throw new RuntimeException("Unable to create application " + app.getClass().getName()+ ": " + e.toString(), e);}}} finally {// If the app targets < O-MR1, or doesn't change the thread policy// during startup, clobber the policy to maintain behavior of b/36951662if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1|| StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {StrictMode.setThreadPolicy(savedPolicy);}}// Preload fonts resourcesFontsContract.setApplicationContextForResources(appContext);if (!Process.isIsolated()) {try {final ApplicationInfo info =getPackageManager().getApplicationInfo(data.appInfo.packageName,PackageManager.GET_META_DATA /*flags*/,UserHandle.myUserId());if (info.metaData != null) {final int preloadedFontsResource = info.metaData.getInt(ApplicationInfo.METADATA_PRELOADED_FONTS, 0);if (preloadedFontsResource != 0) {data.info.getResources().preloadFonts(preloadedFontsResource);}}} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}}

主要就是创建Application,并且调用生命周期onCreate方法。发现在前面介绍的ActivityThread的performLaunchActivity方法中,也有同样的操作,只不过会先判断Application是否已存在。也就是说。正常情况下Application的初始化是在handleBindApplication方法中,并且是创建进程后调用的。performLaunchActivity中只有一个i安策,异常情况Application不存在时才会创建
创建Application后,内部会attach方法,attach内部会调用attachBaseContext方法,atttachBaseContext方法时我们接触到的一个方法,接着才是onCreate方法
再来看根Activity的启动,回到上面的AMS的attachApplicationLocked方法,调用了mAtmInternal.attachApplication方法,mAtmInternal是ActivityTaskManagerInternal实例,具体实现是在ActivityTaskManagerService的内部类LocalService

        @HotPath(caller = HotPath.PROCESS_CHANGE)@Overridepublic boolean attachApplication(WindowProcessController wpc) throws RemoteException {synchronized (mGlobalLockWithoutBoost) {if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);}try {return mRootWindowContainer.attachApplication(wpc);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}}
mRootWindowContainer是RootWindowContainer的实例,看下它的attachApplication方法:
boolean attachApplication(WindowProcessController app) throws RemoteException {boolean didSomething = false;for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {mTmpRemoteException = null;mTmpBoolean = false; // Set to true if an activity was started.final DisplayContent display = getChildAt(displayNdx);display.forAllRootTasks(rootTask -> {if (mTmpRemoteException != null) {return;}if (rootTask.getVisibility(null /* starting */)== TASK_FRAGMENT_VISIBILITY_INVISIBLE) {return;}final PooledFunction c = PooledLambda.obtainFunction(RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,PooledLambda.__(ActivityRecord.class), app,rootTask.topRunningActivity());rootTask.forAllActivities(c);c.recycle();});if (mTmpRemoteException != null) {throw mTmpRemoteException;}didSomething |= mTmpBoolean;}if (!didSomething) {ensureActivitiesVisible(null, 0, false /* preserve_windows */);}return didSomething;}

遍历activity栈,此时理论上应该只有一个根Activity,然后调用mStackSupervisor.realStartActivityLocked方法。
我们发现,根Activity在启动前,需要创建应用进程,然后走到ActivityThread的main方法,开启主线程循环,初始化并绑定Application,赋值IApplicationThread,最后真正的启动过程和普通Activity是一致的。

下面是Activity 的启动流程图
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/29521.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么在JMeter中的实现关联

我们一直用的phpwind这个系统做为演示系统, 如果没有配置好的同学, 请快速配置之后接着往下看哦. phpwind发贴时由于随着登陆用户的改变, verifycode是动态变化的, 因此需要用到关联. LoadRunner的关联函数是reg_save_param, Jmeter的关联则是利用后置处理器来完成. 在需要查…

字节编码学习

字节编码学习 文章目录 字节编码学习01_字节与ASCII码表02_每个国家都有独特的码表03_国际化UTF-804_编码本和解码本不一致&#xff0c;乱码 01_字节与ASCII码表 public class Demo01 {public static void main(String[] args) {// 计算机的底层全部都是字节 ---- ----// 一个…

1.利用matlab建立符号表达式(matlab程序)

1.简述 、 1. 使用sym命令创建符号变量和表达式 语法&#xff1a; sym(‘变量’,参数) %把变量定义为符号对象 说明&#xff1a;参数用来设置限定符号变量的数学特性&#xff0c;可以选择为’positive’、’real’和’unreal’&#xff0c; ’positive’ 表示为“正、实”符…

C++的auto究竟是何方神圣

C的auto究竟是何方神圣 前言&#x1f64c;auto&#xff08;C 11&#xff09; 的使用细则auto是什么&#xff1f; auto声明的变量是在什么时期被编译器推导出来呢&#xff1f;为什么使用auto进行定义变量时&#xff0c;必须进行初始化&#xff1f; auto 的使用场景auto与指针和引…

软件安全测试包含哪些内容和方法?安全测试报告的必要性

软件安全测试是一种通过模拟真实攻击的方式&#xff0c;对软件系统进行全面的安全性评估和测试&#xff0c;以发现潜在的安全漏洞和弱点&#xff0c;是确保软件系统安全性的重要措施。在进行软件安全测试时&#xff0c;我们需要了解测试的内容和方法&#xff0c;以及为什么进行…

FastAPI 构建 API 高性能的 web 框架(一)

如果要部署一些大模型一般langchainfastapi&#xff0c;或者fastchat&#xff0c; 先大概了解一下fastapi,本篇主要就是贴几个实际例子。 官方文档地址&#xff1a; https://fastapi.tiangolo.com/zh/ 1 案例1:复旦MOSS大模型fastapi接口服务 来源&#xff1a;大语言模型工程…

C语言学习笔记 vscode使用外部console-11

前言 在默认情况下&#xff0c;我们运行C语言程序都是在vscode终端的&#xff0c;在小程序运行时这个是没有问题的&#xff0c;但是当程序变得复杂它就不好用了&#xff0c;这时我们可以将这个终端设置为外部console&#xff0c;这样方便处理更多、更复杂的程序。 步骤 1.点击…

PCB电路板设计基础入门学习笔记

文章目录&#xff1a; 一&#xff1a;Arduino线路板绘制&#xff08;原理图库、PCB库、原理图、PCB图绘制&#xff09; 1.原理图库绘制Schematic Library&#xff08;有现成库&#xff0c;没有就自己画&#xff09;[SCH Library] 方法一&#xff1a;自己依次画 ATMEGA328P-…

HTTP——十一、Web的攻击技术

HTTP 一、针对Web的攻击技术1、HTTP 不具备必要的安全功能2、在客户端即可篡改请求3、针对Web应用的攻击模式 二、因输出值转义不完全引发的安全漏洞1、跨站脚本攻击2、SQL 注入攻击3、OS命令注入攻击4、HTTP首部注入攻击5、邮件首部注入攻击6、目录遍历攻击7、远程文件包含漏洞…

【cluster_block_exception】写操作elasticsearch索引报错

【cluster_block_exception】操作elasticsearch索引b报错 背景导致原因&#xff1a;解决方法&#xff1a; 背景 今天线上elk的数据太多&#xff0c;服务器的空间不足了。所以打算删除一些没用用的数据。我是用下面的request&#xff1a; POST /{index_name}/_delete_by_query…

Promise详细版

promise基础原理到难点分析 常见的Promise的方法解读 扩展async和await深入分析 逐步分析Promise底层逻辑代码 一、Promise基础 1.什么是promise 为了解决回调地狱&#xff1a; //2.设置点击事件btn.onclick function() {//3.创建ajax实例化对象let xhr new XMLHttpRe…

流量,日志分析

wireshark wireshark中有捕获过滤器和显示过滤器 常用的捕获过滤表达式&#xff1a; 常见的显示过滤表达式&#xff1a; 语法&#xff1a; 1.过滤IP&#xff0c;如来源IP或者目标IP等于某个IP 例子: ip.src eq 192.168.1.107 or ip.dst eq 192.168.1.107 或者 ip.addr eq 1…

DAY03_Spring—SpringAOPAOP切入点表达式AOP通知类型Spring事务管理

目录 一 AOP1 AOP简介问题导入1.1 AOP简介和作用1.2 AOP中的核心概念 2 AOP入门案例问题导入2.1 AOP入门案例思路分析2.2 AOP入门案例实现【第一步】导入aop相关坐标【第二步】定义dao接口与实现类【第三步】定义通知类&#xff0c;制作通知方法【第四步】定义切入点表达式、配…

(八)穿越多媒体奇境:探索Streamlit的图像、音频与视频魔法

文章目录 1 前言2 st.image&#xff1a;嵌入图像内容2.1 图像展示与描述2.2 调整图像尺寸2.3 使用本地文件或URL 3 st.audio&#xff1a;嵌入音频内容3.1 播放音频文件3.2 生成音频数据播放 4 st.video&#xff1a;嵌入视频内容4.1 播放视频文件4.2 嵌入在线视频 5 结语&#x…

MySQL面试1

Mysql的面试突击1 Mysql的体系结构是什么样子的&#xff08;查询语句怎么进行执行的&#xff09; mysql的架构&#xff1a;单进程多线程的架构模式 CLient -----> Server架构 Mysql的链接方式有没有性能优化的点 2个点 查询缓存(Query Cache) MySQL 内部自带了一个缓存模…

Spring Boot集成EasyExcel实现excel导入导出操作

文章目录 Spring Boot集成EasyExcel实现excel导入导出操作0 简要说明简单使用读操作excel源文件实体类监听器业务代码 写操作*实体类*excel示例业务代码根据参数指定列导出指定哪几列导出复杂头导出 关于数值型&#xff0c;日期型&#xff0c;浮点型数据解决方案实体类接收字符…

算法通过村第二关-链表黄金笔记|K个一组反转

文章目录 前言链表反转|K个一组翻转链表解题方法&#xff1a;头插法处理&#xff1a;穿针引线法处理&#xff1a; 总结 前言 提示&#xff1a;没有人天生就喜欢一种气味而讨厌另一种气味。文明的暗示而已。 链表反转|K个一组翻转链表 给你链表的头节点 head &#xff0c;每 k…

【css】textarea-通过resize:none 禁止拖动设置大小

使用 resize 属性可防止调整 textareas 的大小&#xff08;禁用右下角的“抓取器”&#xff09;&#xff1a; 没有设置resize:none 代码&#xff1a; <!DOCTYPE html> <html> <head> <style> textarea {width: 100%;height: 150px;padding: 12px 20p…

源码分析——HashMap(JDK1.8)源码+底层数据结构分析

文章目录 HashMap 简介底层数据结构分析JDK1.8之前JDK1.8之后 HashMap源码分析构造方法put方法get方法resize方法 HashMap常用方法测试 HashMap 简介 HashMap 主要用来存放键值对&#xff0c;它基于哈希表的Map接口实现&#xff0c;是常用的Java集合之一。 JDK1.8 之前 HashM…

HBase-写流程

写流程顺序正如API编写顺序&#xff0c;首先创建HBase的重量级连接 &#xff08;1&#xff09;读取本地缓存中的Meta表信息&#xff1b;&#xff08;第一次启动客户端为空&#xff09; &#xff08;2&#xff09;向ZK发起读取Meta表所在位置的请求&#xff1b; &#xff08;…