Activity的创建过程源码分析
一、概述
Activity的启动过程,涉及到多个进程以及跨进程通信IPC,总体的时序图如下所示,这种情况是打开新应用进程Activity的过程。

二、源码分析过程
1.Activity A 发起startActivity,如下:

会调用到Instrumentation的execStartActivity方法:
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {IApplicationThread whoThread = (IApplicationThread) contextThread;try {//这里的调用是一个IPC过程,会调用到 ActivityTaskManagerService 的远程方法int result = ActivityTaskManager.getService().startActivity(whoThread,who.getOpPackageName(), who.getAttributionTag(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()), token,target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;}
这里我们看到,调用了ActivityTaskManager提供的远程接口,并且传入了一堆参数进去,主要的参数有intent、token、whoThread。intent我们都知道这是表示一个意图,也就是我们想要启动的Activity的信息都包含在这此。后面两个参数咱们等会儿再说。
2.ATMS的内部处理
这一步已经来到了system_server进程。ActivityTaskManagerService继承了IActivityTaskManager.Stub接口,是Binder接口的实现类,作为一个系统服务存在于system_server进程中。
ActivityTaskManagerService会调用到如下方法:
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) {return getActivityStartController().obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setCallingFeatureId(callingFeatureId).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setUserId(userId) //此处就会把mRequest.mayWait设置为true.execute();}
这里obtainStarter会获取ActivityStarter,并执行了ActivityStarter的execute()方法,然后一步步调用,创建了本次将要启动的ActivityRecord:
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,mSupervisor, checkedOptions, sourceRecord); //创建一个ActivityRecord,这就是将要发起的Activity在AMS中的数据结构
然后进入到比较核心的方法startActivityUnchecked(),如下:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,ActivityRecord[] outActivity, boolean restrictedBgActivity) {computeLaunchingTaskFlags(); //推测lunchmode,主要目的是当sourceRecord为null的时候,需要|FLAG_ACTIVITY_NEW_TASKcomputeSourceStack(); //查看sourceStack的状态,是否是finishingActivityRecord reusedActivity = getReusableIntentActivity(); //如果不设置启动模式为FLAG_ACTIVITY_NEW_TASK,此处返回为nullif (dontStart) {//如果发起发activity是null,并且栈顶里面的activity和将要发起的activity名字相同等等逻辑,才重复使用栈顶activity,且回调newIntent//一般情况不会走进这里......}boolean newTask = false;final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) //taskToAffiliate通常为null ? mSourceRecord.getTaskRecord() : null;// Should this be considered a new task?int result = START_SUCCESS;if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {newTask = true; //表示没有依附的task,所以需要另起一个result = setTaskFromReuseOrCreateNewTask(taskToAffiliate); //重复使用TaskRecord或者创建一个新的TaskRecord} else if (mSourceRecord != null) {result = setTaskFromSourceRecord(); //不设置launchmode,正常情况会走这里} else if (mInTask != null) {result = setTaskFromInTask();} else {// This not being started from an existing activity, and not part of a new task...// just put it in the top task, though these days this case should never happen.result = setTaskToCurrentTopOrCreateNewTask(); //不考虑此种情况}mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,mOptions); if (mDoResume) {......mRootActivityContainer.resumeFocusedStacksTopActivities(mTargetStack, mStartActivity, mOptions);}mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);return START_SUCCESS;
}
这一步主要是判定新建的Activity应该归属哪个TaskRecord、ActivityStack,默认情况下会调用setTaskFromSourceRecord()这个方法,即新建的Activity默认是属于发起方Activity所在的TaskRecord。
下一步就是RootActivityContainer的resumeFocusedStacksTopActivities方法,去显示出这个Activity。这个方法又会调用到ActivityStack内部:
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {pausing |= startPausingLocked(userLeaving, false, next, false); //终止当前的activity......if (next.attachedToProcess()) {}else{mStackSupervisor.startSpecificActivityLocked(next, true, true); //需要重新启动这个activity}}
这里就会把当前还在显示的Activity onPause掉。也就是先onpause上一个Activity,然后才会显示下一个Activity。
接着继续调用到了ActivityStackSupervisor里面:
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {// Is this activity's application already running?final WindowProcessController wpc =mService.getProcessController(r.processName, r.info.applicationInfo.uid);if (wpc != null && wpc.hasThread()) {realStartActivityLocked(r, wpc, andResume, checkConfig); //如果对应的进程存在,则去打开activityreturn;}// Post message to start process to avoid possible deadlock of calling into AMS with the //不存在对应的进程,需要先创建进程// ATMS lock held.final Message msg = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());mService.mH.sendMessage(msg);}
这里会判断Activity对应的进程是否存在,如果不存在,那么就会给ActivityManagerService发送一条创建新进程的消息。
消息进入到ActivityManagerService:
final ProcessRecord startProcessLocked(String processName,ApplicationInfo info, boolean knownToBeDead, int intentFlags,HostingRecord hostingRecord, boolean allowWhileBooting,boolean isolated, boolean keepIfLarge) {return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,null /* crashHandler */);}
ProcessList内部会创建一个AppZygote对象,然后孵化出新的进程:
final String entryPoint = "android.app.ActivityThread";private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,String seInfo, String requiredAbi, String instructionSet, String invokeWith,long startTime) {final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);startResult = appZygote.getProcess().start(entryPoint, //这里调用Zygote去创建一个新的进程app.processName, uid, uid, gids, runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, null, app.info.packageName,/*useUsapPool=*/ false,new String[] {PROC_START_SEQ_IDENT + app.startSeq});}
3.新创建应用进程的处理
一个Android应用进程,它的主程序入口就在ActivityThread,这在上面的 entryPoint = "android.app.ActivityThread"可以找到一些踪迹。
public static void main(String[] args) {Looper.prepareMainLooper(); //初始化looperActivityThread thread = new ActivityThread();thread.attach(false, startSeq); //attach就是把这个新创建的进程关联到AMS中Looper.loop();}
private void attach(boolean system, long startSeq) {final IActivityManager mgr = ActivityManager.getService();mgr.attachApplication(mAppThread, startSeq); //ApplicationThread是一个Binder接口的本地实现//这是一次IPC过程,会调用ActivityManagerService服务中对应的方法}
这里传入的mAppThread类型是ApplicationThread,它是IApplicationThread的Binder接口本地实现类,用来接收AMS等其他进程的信息,具体的接口我们后面讲。
至此,流程又来到了AMS这一边。
4.AMS处理attach信息
ActivityManagerService处理attachApplication的调用,主要是把进程名等信息,通过IApplicationThread给到新创建的应用进程:
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {ProcessRecord app;app = mPidsSelfLocked.get(pid);final String processName = app.processName;final ActiveInstrumentation instr = app.getActiveInstrumentation();ApplicationInfo appInfo = instr != null ? instr.mTargetInfo : app.info;thread.bindApplication(processName, appInfo, providers, null, profilerInfo, //这里把进程的信息,通过IApplicationThread这个Binder接口传递给新创建的进程null, null, null, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()),app.compat, getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions); app.makeActive(thread, mProcessStats);}
在执行完bindApplication之后,ActivityManagerService会继续调用到RootActivityContainer里面的方法,找到与此进程相关联的Activity,并打开此Activity:
mStackSupervisor.realStartActivityLocked(activity, app, top == activity /* andResume */, true /* checkConfig */))
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,boolean andResume, boolean checkConfig) throws RemoteException {final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.appToken);clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),r.icicle, r.persistentState, results, newIntents,dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),r.assistToken));mService.getLifecycleManager().scheduleTransaction(clientTransaction);}
这里的ClientTransaction,具备IPC的能力,通过它内部的IApplicationThread Binder接口,它会把自己作为参数传递给对应要操作的进程。本次的事务处理,ClientTransaction添加了一个LaunchActivityItem,说明这是要显示Activity的意图。
5.应用进程接收信息后的处理
应用进程首先会接收到AMS对bindApplication的回调,接收的位置是在ApplicationThread内部,它是IApplicationThread的本地实现:
private class ApplicationThread extends IApplicationThread.Stub {public final void bindApplication(String processName, ApplicationInfo appInfo, //这里会接收到来自AMS的绑定信息,主要是processName和ApplicationInfoList providers, ComponentName instrumentationName,ProfilerInfo profilerInfo, Bundle instrumentationArgs,IInstrumentationWatcher instrumentationWatcher,IUiAutomationConnection instrumentationUiConnection, int debugMode,boolean enableBinderTracking, boolean trackAllocation,boolean isRestrictedBackupMode, boolean persistent, Configuration config,CompatibilityInfo compatInfo, Map services, Bundle coreSettings,String buildSerial, AutofillOptions autofillOptions,ContentCaptureOptions contentCaptureOptions) {setCoreSettings(coreSettings);AppBindData data = new AppBindData();data.processName = processName;data.appInfo = appInfo;data.providers = providers;......sendMessage(H.BIND_APPLICATION, data); //给主线程Handler H 发送送一条信息,交由H处理}
}
class H extends Handler {case BIND_APPLICATION:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;}
private void handleBindApplication(AppBindData data) {// send up app name; do this *before* waiting for debuggerProcess.setArgV0(data.processName); //进程设置名称VMRuntime.setProcessPackageName(data.appInfo.packageName); //设置包名final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); //创建ContextImplmInstrumentation = (Instrumentation)cl.loadClass(data.instrumentationName.getClassName()).newInstance(); //创建mInstrumentationmInstrumentation.init(this, instrContext, appContext, component,data.instrumentationWatcher, data.instrumentationUiAutomationConnection);Application app;app = data.info.makeApplication(data.restrictedBackupMode, null); //利用反射创建了Manifest文件中对应的ApplicationmInstrumentation.onCreate(data.instrumentationArgs);mInstrumentation.callApplicationOnCreate(app); //调用Application的onCreat()方法}
在这里初始化了Android的上下文环境,同时还初始化了Application,并且回调了Application的onCreat()方法。
然后应用进程会收到ClientTransaction的方法回调:
private class ApplicationThread extends IApplicationThread.Stub {@Overridepublic void scheduleTransaction(ClientTransaction transaction) throws RemoteException {ActivityThread.this.scheduleTransaction(transaction);}......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);}
}
在接收到scheduleTransaction的回调之后,还是会把消息给到ApplicationThread的H处理,H会把ClientTransaction这个消息给到TransactionExecutor处理:
public void executeCallbacks(ClientTransaction transaction) {final List callbacks = transaction.getCallbacks();for (int i = 0; i < size; ++i) {final ClientTransactionItem item = callbacks.get(i); //这里的item是LaunchActivityItemitem.execute(mTransactionHandler, token, mPendingActions);item.postExecute(mTransactionHandler, token, mPendingActions);}}
发现TransactionExecutor会去执行ClientTransactionItem 内部的逻辑,这里是LaunchActivityItem:
public class LaunchActivityItem extends ClientTransactionItem {public void execute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) {Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,mPendingResults, mPendingNewIntents, mIsForward,mProfilerInfo, client, mAssistToken);client.handleLaunchActivity(r, pendingActions, null /* customIntent */); }
这里的client就是ActivityThread,ActivityThread实现了ClientTransactionHandler。于是这里就调用到了ActivityThread的handleLaunchActivity方法,同时把Activity的相关信息封装成了ActivityClientRecord 这个数据结构作为参数传递。
接下来就来到了熟悉的handleLaunchActivity方法:
public Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {WindowManagerGlobal.initialize(); //获取WindowManagerServicefinal Activity a = performLaunchActivity(r, customIntent);return a;}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {ContextImpl appContext = createBaseContextForActivity(r); java.lang.ClassLoader cl = appContext.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); //最终是AppComponentFactory利用反射生成Activityactivity.attach(appContext, this, getInstrumentation(), r.token, //activity关联相关的信息,包括创建PhoneWindowr.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback,r.assistToken);mInstrumentation.callActivityOnCreate(activity, r.state); //这里会回调Activity的OnCreate回调方法}
在回调了OnCreate方法之后,我们的Activity就算创建完毕啦。下一步就是在设置过contentview之后,attach到WMS上显示出来了。
三、Q&A
1.Q:一个新的Activity启动过程,生命周期顺序是怎样的?
A:发起方为Activity A,新启动的为Activity B,那么:
A onPause() -> B Application onCreate() -> B onCreate() -> B onStart() ->B onResume() -> A onStop() -> A onDestroy()
2.Q:AMS和APP进程怎么通信?
A:APP想要跟AMS通信,可以通过Android SDK提供的系统类ActivityManager,去获取到Binder的Client端接口,然后向AMS发送消息。
APP想要跟ATMS通信,如最常见的startActivity,同样也是通过Android SDK提供的系统类ActivityTaskManager,获取Binder接口。
AMS想要跟APP通信,是通过IApplicationThread这个Binder接口来完成的。APP在创建的时候,会把自己实现了的IApplicationThread传递给AMS,这样AMS就拿到了对应APP的句柄,通过这个句柄跟APP通信。
3.Q:Activity里面的mToken是什么?有什么作用?
A:mToken的类型是Token,是ActivityRecord的内部成员,也是它的内部类
final IApplicationToken.Stub appToken; // window manager tokenstatic class Token extends IApplicationToken.Stub {private final WeakReference weakActivity;private final String name;Token(ActivityRecord activity, Intent intent) {weakActivity = new WeakReference<>(activity);name = intent.getComponent().flattenToShortString();} ......}
在ActivityRecord的构造函数内创建的
appToken = new Token(this, _intent);
AMS在执行realStartActivity的调用时,传递给对应的APP。
appToken会被保存在应用进程的ActivityClientRecord和Activity中。并且Token还会被传递给WMS等一些其他服务中去。
可以看出Token代表的是一个唯一的Activity,它是一种可以在不同进程间传递的介质,获取到Token就可以标定这个Activity。
4.Q:Application什么时候创建的?它和Context是什么关系?
A:Application是在应用进程创建后,AMS绑定应用程序时创建的。
它创建后会回调Android系统框架下应用的第一个生命周期函数。
Application继承自ContextWrapper,也就是继承自Context。它因此也拥有Context所定义的,提供整个Android系统环境接口的能力。
但是Application提供上下文的能力不是有它自己实现的,而是由创建Application的时候传入了一个ContextImpl提供。
5.Q: 设置了singleTask模式,启动Activity的时候就会创建新的Task任务栈吗?
A:不一定,如果新启动的Activity的所属的任务栈已经存在,那么就不会创建新的任务栈。
怎么判断这个Activity的所属的任务栈,我们可以简单理解为任务栈名称相同,这就涉及到taskAffinity。
taskAffinity属性默认值就是应用包名。在manifest文件中也可以手动设置这个属性。
Task任务栈中的taskAffinity是UID加上XML中的taskAffinity属性一起组合的,类似于如下:
taskAffinity=10007:com.example.activitytest01
那么也就是说两个不同进程的Activity,虽然设置的taskAffinity属性是一样的,但是它们是属于不同的任务栈。
taskAffinity属性只有在设置了singleTask,新创建Task任务栈的时候才有用。
6.Q:Task任务栈和应用程序的关系
A:TaskRecord是一系列Activity的集合,但这些Activity并不一定属于同一个应用程序。
同一个应用程序,它内部的Activity也可能会属于不同的TaskRecord。
一个Activity,它始终会运行在自己所在的应用进程,但是它可能却存在于另外一个应用进程建立的Task任务栈中。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
