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.java
E:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/RootWindowContainer.java
E:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/Task.java
E:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/TaskFragment.java
E:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/ActivityTaskSupervisor.java
E:\AOSP_12\frameworks\base\core\java\android\app\servertransaction/ClientTransaction.java
E:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/ActivityTaskManagerService.java
E:\AOSP_12\frameworks\base\services\core\java\com\android\server\wm/ClientLifecycleManager.java
E:\AOSP_12\frameworks\base\core\java\android\app/IApplicationThread.aidl
E:\AOSP_12\frameworks\base\core\java\android\app/ActivityThread.java
E:\AOSP_12\frameworks\base\core\java\android\app/ClientTransactionHandler.java
E:\AOSP_12\frameworks\base\core\java\android\app\servertransaction/TransactionExecutor.java
E:\AOSP_12\frameworks\base\core\java\android\app\servertransaction/ActivityLifecycleItem.java
E:\AOSP_12\frameworks\base\core\java\android\app\servertransaction/LaunchActivityItem.java
E:\AOSP_12\frameworks\base\core\java\android\app\servertransaction/ClientTransactionItem.java
ClientTransactionItem的所有子类或者相关类均在 frameworks/base/core/java/android/app/servertransaction/目录下
E:\AOSP_12\frameworks\base\services\core\java\com\android\server\am/ActivityManagerService.java
E:\AOSP_12\frameworks\base\services\core\java\com\android\server\am/ProcessList.java
E:\AOSP_12\frameworks\base\core\java\android\os/Process.java
E:\AOSP_12\frameworks\base\core\java\android\os/ZygoteProcess.java
一、Activity的启动的发起
启动Activity先从startActivity开始,点击startActivity进入ContextWrapper类中由于mBase对象是context,Context的实现类为ContextImpl,所以直接看ContextImpl类中的startActivity方法
@OverridepublicvoidstartActivity(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.finalint 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)){thrownewAndroidRuntimeException("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方法:
@UnsupportedAppUsagepublicActivityResultexecStartActivity(Context who,IBinder contextThread,IBinder token,String target,Intent intent,int requestCode,Bundle options){IApplicationThread whoThread =(IApplicationThread) contextThread;if(mActivityMonitors !=null){synchronized(mSync){finalintN= mActivityMonitors.size();for(int i=0; i<N; i++){finalActivityMonitor 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;}elseif(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){thrownewRuntimeException("Failure from system", e);}returnnull;}
可以看到Activity的启动又交给了ActivityTaskManager.getService()
publicstaticIActivityTaskManagergetService(){returnIActivityTaskManagerSingleton.get();}@UnsupportedAppUsage(trackingBug =129726065)privatestaticfinalSingleton<IActivityTaskManager>IActivityTaskManagerSingleton=newSingleton<IActivityTaskManager>(){@OverrideprotectedIActivityTaskManagercreate(){finalIBinder b =ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);returnIActivityTaskManager.Stub.asInterface(b);}};
这里是获取一个跨进程的服务,获取的服务是ActivityTaskManagerService(ATMS),它继承于IActivityTaskManager.stub,是一个Bindder对象,并且是通过单例提供服务的,ATMS是用于管理Activity及其容器(任务,堆栈、显示等)的系统服务,运行在系统服务进程(system_server)之中。
二 Activity的管理——ATMS
在ActivityTaskManagerService里面调用startActivity方法,如下:
@OverridepublicfinalintstartActivity(IApplicationThread caller,String callingPackage,String callingFeatureId,Intent intent,String resolvedType,IBinder resultTo,String resultWho,int requestCode,int startFlags,ProfilerInfo profilerInfo,Bundle bOptions){returnstartActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId());}@OverridepublicintstartActivityAsUser(IApplicationThread caller,String callingPackage,String callingFeatureId,Intent intent,String resolvedType,IBinder resultTo,String resultWho,int requestCode,int startFlags,ProfilerInfo profilerInfo,Bundle bOptions,int userId){returnstartActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,true/*validateIncomingUser*/);}privateintstartActivityAsUser(IApplicationThread caller,String callingPackage,@NullableString 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对象//采用工厂设计模式+享元设计+链式调用returngetActivityStartController().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 =newPendingRemoteAnimationRegistry(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.
*/ActivityStarterobtainStarter(Intent intent,String reason){return mFactory.obtain().setIntent(intent).setReason(reason);}voidonExecutionComplete(ActivityStarter starter){if(mLastStarter ==null){
mLastStarter = mFactory.obtain();}
mLastStarter.set(starter);
mFactory.recycle(starter);}staticclassDefaultFactoryimplementsFactory{/**
* 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)
*
*/privatefinalintMAX_STARTER_COUNT=3;//ActivitySatrter 最大数量privateActivityStartController mController;privateActivityTaskManagerService mService;privateActivityTaskSupervisor mSupervisor;privateActivityStartInterceptor mInterceptor;//同步池privateSynchronizedPool<ActivityStarter> mStarterPool =newSynchronizedPool<>(MAX_STARTER_COUNT);DefaultFactory(ActivityTaskManagerService service,ActivityTaskSupervisor supervisor,ActivityStartInterceptor interceptor){
mService = service;
mSupervisor = supervisor;
mInterceptor = interceptor;}@OverridepublicvoidsetController(ActivityStartController controller){
mController = controller;}@OverridepublicActivityStarterobtain(){//从同步池中获取ActivityStarter对象ActivityStarter starter = mStarterPool.acquire();if(starter ==null){if(mService.mRootWindowContainer ==null){thrownewIllegalStateException("Too early to start activity.");}
starter =newActivityStarter(mController, mService, mSupervisor, mInterceptor);}return starter;}@Overridepublicvoidrecycle(ActivityStarter starter){
starter.reset(true/* clearRequest*/);
mStarterPool.release(starter);}}
可以看到,默认的工厂在提供了一个容量为3的同步缓存池来缓存ActivityStarter对象,该对象创建完成之后,ActivityTaskManagerService就会将接下来启动Activity的操作交给ActivityStarter来完成
intexecute(){try{// Refuse possible leaked file descriptors//拒绝可能泄露的文件描述符if(mRequest.intent !=null&& mRequest.intent.hasFileDescriptors()){thrownewIllegalArgumentException("File descriptors passed in Intent");}..省略部分代码...
res =executeRequest(mRequest);//开始执行请求..省略部分代码...returngetExternalResult(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做任务栈管理。
*/privateintexecuteRequest(Request request){...省略部分代码...//创建出我们的目标ActivityRecord对象,存到传入数组0索引上finalActivityRecord r =newActivityRecord.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,也就是当前activity
mLastStartActivityResult =startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags,true/* doResume */, checkedOptions,
inTask, inTaskFragment, restrictedBgActivity, intentGrants);...省略部分代码....return mLastStartActivityResult;}
在executeRequest方法中会进行一些校验和判断权限,包括进程检测,intent检查,权限检查等,后面会创建ActivityRecord,每个Activity都会对应一个ActivityRecord对象,接着就会调用startActivityUnChecked方法对要启动的Activity做任务栈管理。
privateintstartActivityUnchecked(finalActivityRecord 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);finalboolean 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){finalTask targetRootTask =
mTargetRootTask !=null? mTargetRootTask : mTargetTask.getRootTask();
targetRootTask.setAlwaysOnTop(true);}}finally{..省略部分代码...}}postStartActivityProcessing(r, result, startedActivityRootTask);return result;}
在大多数初步检查已经完成的情况下开始进行下一步确认拥有必要的权限。核心方法就是调用startActivityInner()用来检查启动所必须要有的权限
intstartActivityInner(finalActivityRecord 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.finalTask prevTopTask = mPreferredTaskDisplayArea.getFocusedRootTask();//决定是否应将新Activity插入Task中。返回null,如果不是则应将新Activity添加到其中的task进行Activity记录。//查找可用的任务栈finalTask 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则计算是否存在可以使用的任务栈finalTask targetTask = reusedTask !=null? reusedTask :computeTargetTask();//是否需要创建栈finalboolean 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;}finalActivityRecord 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相同//则需要检查它是否应该只启动一次finalTask 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){//新建一个TaskfinalTask taskToAffiliate =(mLaunchTaskBehind && mSourceRecord !=null)? mSourceRecord.getTask():null;//将Activity放入新建的任务栈setNewTask(taskToAffiliate);}elseif(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 UIDsfinalPackageManagerInternal pmInternal =
mService.getPackageManagerInternalLocked();finalint 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*/);}finalTask 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);finalboolean isTaskSwitch = startedTask != prevTopTask &&!startedTask.isEmbedded();//创建启动黑白屏window
mTargetRootTask.startActivityLocked(mStartActivity,
topRootTask !=null? topRootTask.getTopNonFinishingActivity():null, newTask,
isTaskSwitch, mOptions, sourceRecord);if(mDoResume){finalActivityRecord 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");}//启动栈中顶部的Activity
mRootWindowContainer.resumeFocusedTasksTopActivities(
mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);}}
mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);// Update the recent tasks list immediately when the activity starts
mSupervisor.mRecentTasks.add(startedTask);
mSupervisor.handleNonResizableTaskIfNeeded(startedTask,
mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);returnSTART_SUCCESS;}
在上面方法中,根据启动模式计算出flag,然后在根据flag等条件判断要启动的Activity的ActivityRecord是需要新创建Task栈还是加入到现有的Task栈中。在位Activity准备好Task栈之后,调用了mRootWindowContainer.resumeFocuredTasksTopActivities方法。
RootWindowContainer是窗口容器(WindowContainer)的根容器,管理所有的窗口容器,设备上所有的窗口(Window)显示器(Display)都是由它来管理的
下面看mRootWindowContainer.resumeFocursedTasksTopActivities方法的具体操作
booleanresumeFocusedTasksTopActivities(Task targetRootTask,ActivityRecord target,ActivityOptions targetOptions,boolean deferPause){if(!mTaskSupervisor.readyToResume()){returnfalse;}boolean result =false;if(targetRootTask !=null&&(targetRootTask.isTopRootTaskInDisplayArea()||getTopDisplayFocusedRootTask()== targetRootTask)){
result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
deferPause);}for(int displayNdx =getChildCount()-1; displayNdx >=0;--displayNdx){finalDisplayContent display =getChildAt(displayNdx);finalboolean curResult = result;boolean[] resumedOnDisplay =newboolean[1];
display.forAllRootTasks(rootTask ->{finalActivityRecord 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.//获取当前屏幕设备的焦点任务栈finalTask focusedRoot = display.getFocusedRootTask();if(focusedRoot !=null){//如果焦点任务栈不为空则唤醒顶部的Activity
result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions);}elseif(targetRootTask ==null){//否则唤醒首页Activity
result |=resumeHomeActivity(null/* prev */,"no-focusable-task",
display.getDefaultTaskDisplayArea());}}}return result;}
mRootWindowContainer.resumeFocusedStacksToActivities()方法会恢复对应任务栈顶部的Activity,方法中会检查一些可见性相关的属性,后转交给Task调用resumeTopActivityUncheckedLocked方法来继续启动流程。
/*
/*
* 确保恢复根task中的顶部activity
**/@GuardedBy("mService")booleanresumeTopActivityUncheckedLocked(ActivityRecord prev,ActivityOptions options,boolean deferPause){if(mInResumeTopActivity){// Don't even start recursing.returnfalse;}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){finalTask 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.finalActivityRecord next =topRunningActivity(true/* focusableOnly */);if(next ==null||!next.canTurnScreenOn()){checkReadyForSleep();}}finally{
mInResumeTopActivity =false;}return someActivityResumed;}/** @see #resumeTopActivityUncheckedLocked(ActivityRecord, ActivityOptions, boolean) */@GuardedBy("mService")booleanresumeTopActivityUncheckedLocked(ActivityRecord prev,ActivityOptions options){returnresumeTopActivityUncheckedLocked(prev, options,false/* skipPause */);}/**
* Task用来描述一个Activity的任务栈
*/@GuardedBy("mService")privatebooleanresumeTopActivityInnerLocked(ActivityRecord prev,ActivityOptions options,boolean deferPause){if(!mAtmService.isBooting()&&!mAtmService.isBooted()){// Not ready yet!returnfalse;}//在当前Task栈中找到最上层正在运行的Activity//如果这个Activity没有获取焦点,那这个Activity将会被重新启动//获取当前顶部正在运行的ActivityfinalActivityRecord topActivity =topRunningActivity(true/* focusableOnly */);if(topActivity ==null){// There are no activities left in this task, let's look somewhere else.//如果根任务栈为空则返回下一个焦点ActivityreturnresumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);}finalboolean[] resumed =newboolean[1];//获取当前顶部正在运行的Activity的TaskFragmentfinalTaskFragment topFragment = topActivity.getTaskFragment();//唤醒
resumed[0]= topFragment.resumeTopActivity(prev, options, deferPause);forAllLeafTaskFragments(f ->{if(topFragment == f){return;}if(!f.canBeResumed(null/* starting */)){return;}//调用TaskFragment的一个关键方法resumeTopActivity来继续唤醒顶部Activity
resumed[0]|= f.resumeTopActivity(prev, options, deferPause);},true);return resumed[0];}
跟踪代码执行到TaskFragment
finalbooleanresumeTopActivity(ActivityRecord prev,ActivityOptions options,boolean deferPause){ActivityRecord next =topRunningActivity(true/* focusableOnly */);if(next ==null||!next.canResumeByCompat()){returnfalse;}
next.delayedResume =false;finalTaskDisplayArea 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);returnfalse;}// If we are currently pausing an activity, then don't do anything until that is done.finalboolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();if(!allPausedComplete){ProtoLog.v(WM_DEBUG_STATES,"resumeTopActivity: Skip resume: some activity pausing.");returnfalse;}// 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");returnfalse;}// 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");returnfalse;}// 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;finalTask 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);//暂停栈顶的Activity
pausing |=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()){//为false
next.app.updateProcessInfo(false/* updateServiceConnectionActivities */,true/* activityChange */,false/* updateOomAdj */,false/* addPendingTopUid */);}elseif(!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.finalboolean isTop =this== taskDisplayArea.getFocusedRootTask();
mAtmService.startProcessAsync(next,false/* knownToBeDead */, isTop,
isTop ?"pre-top-activity":"pre-activity");}if(lastResumed !=null){
lastResumed.setWillCloseOrEnterPip(true);}returntrue;}elseif(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);returntrue;}// 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;finalDisplayContent 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.finalboolean 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();finalActivityRecord.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();returntrue;}try{//开启一个事务finalClientTransaction transaction =ClientTransaction.obtain(next.app.getThread(), next.appToken);// Deliver all pending results.ArrayList<ResultInfo> a = next.results;if(a !=null){finalint 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最终的生命周期状态为onResume
transaction.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;}elseif(SHOW_APP_STARTING_PREVIEW&& lastFocusedRootTask !=null&& lastFocusedRootTask.isTopRootTaskInDisplayArea()){
next.showStartingWindow(false/* taskSwitch */);}//Activity的启动事务就是在realStartActivityLocked方法中启动
mTaskSupervisor.startSpecificActivity(next,true,false);returntrue;}// 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 */);returntrue;}}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);//启动指定的Activity
mTaskSupervisor.startSpecificActivity(next,true,true);}returntrue;}
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 ,代码如下:
voidstartSpecificActivity(ActivityRecord r,boolean andResume,boolean checkConfig){// Is this activity's application already running?//获取目标进程finalWindowProcessController 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();finalboolean 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()方法。
booleanrealStartActivityLocked(ActivityRecord r,WindowProcessController proc,boolean andResume,boolean checkConfig)throwsRemoteException{//传递过来的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);returnfalse;}finalTask task = r.getTask();finalTask 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);}finalint 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.finalIActivityClientController activityClientController =
proc.hasEverLaunchedActivity()?null: mService.mActivityClientController;
r.launchCount++;
r.lastLaunchTime =SystemClock.uptimeMillis();
proc.setLastActivityLaunchTime(r.lastLaunchTime);if(DEBUG_ALL)Slog.v(TAG,"Launching: "+ r);finalLockTaskController 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()){thrownewRemoteException();}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.finalConfiguration procConfig = proc.prepareConfigurationForLaunchingActivity();finalMergedConfiguration mergedConfiguration =newMergedConfiguration(
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的内部类ApplicationThreadfinalClientTransaction clientTransaction =ClientTransaction.obtain(
proc.getThread(), r.appToken);finalboolean isTransitionForward = r.isTransitionForward();//为事务设置Callback LaunchActivityItem,在客户端时会被调用//添加LaunchActivityItem
clientTransaction.addCallback(LaunchActivityItem.obtain(newIntent(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应该到达那个生命周期finalActivityLifecycleItem 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 */);returnfalse;}// 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();}returntrue;}
代码如上: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.java
ClientLifecycleManagergetLifecycleManager(){return mLifecycleManager;}
可以看到,getLifecycleManager返回了一个ClientLifecycleManager的实例,并调用了scheduleTransaction方法,代码如下:
voidscheduleTransaction(ClientTransaction transaction)throwsRemoteException{finalIApplicationThread client = transaction.getClient();//执行事务,会调用ClientTransaction的schedule方法
transaction.schedule();if(!(client instanceofBinder)){// 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
*/voidscheduleTransaction(@NonNullIApplicationThread client,@NonNullIBinder activityToken,@NonNullActivityLifecycleItem stateRequest)throwsRemoteException{finalClientTransaction 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
@OverridepublicvoidscheduleTransaction(ClientTransaction transaction)throwsRemoteException{ActivityThread.this.scheduleTransaction(transaction);}
在ActivityThread的类里面发现没有实现scheduleTransaction方法,想到子类可以调用父类的方法,所以可以去ClientTransactionHandler.java类里面去查找scheduleTransaction方法
voidscheduleTransaction(ClientTransaction transaction){//处理
transaction.preExecute(this);//发送消息sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);}
这里将transaction作为参数调用了sendMessage方法。
voidsendMessage(int what,Object obj){sendMessage(what, obj,0,0,false);}privatevoidsendMessage(int what,Object obj,int arg1){sendMessage(what, obj, arg1,0,false);}privatevoidsendMessage(int what,Object obj,int arg1,int arg2){sendMessage(what, obj, arg1, arg2,false);}privatevoidsendMessage(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可以看到如下代码:
caseEXECUTE_TRANSACTION:finalClientTransaction 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。
publicvoidexecute(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的代码如下:
@VisibleForTestingpublicvoidexecuteCallbacks(ClientTransaction transaction){finalList<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");finalIBinder 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).finalActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();finalint finalState = finalStateRequest !=null? finalStateRequest.getTargetState():UNDEFINED;// Index of the last callback that requests some post-execution state.finalint lastCallbackRequestingState =lastCallbackRequestingState(transaction);finalint size = callbacks.size();//遍历callbacks数组for(int i =0; i < size;++i){//从callbacks数组中取出itemfinalClientTransactionItem item = callbacks.get(i);if(DEBUG_RESOLVER)Slog.d(TAG,tId(transaction)+"Resolving callback: "+ item);finalint postExecutionState = item.getPostExecutionState();finalint 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.finalboolean 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 最终的生命周期状态为 Resume
transaction.setLifecycleStateRequest(ResumeActivityItem.obtain(next.app.getReportedProcState(),
dc.isNextTransitionForward()));
设置了ResumeActivityItem后,接下俩看看executeLifecycleState方法的源码:
privatevoidexecuteLifecycleState(ClientTransaction transaction){//获取ActivityLifecycleItem,这里获取的是我们之前添加的ResumeActivityItemfinalActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();if(lifecycleItem ==null){// No lifecycle request, return early.return;}finalIBinder token = transaction.getActivityToken();finalActivityClientRecord 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的execute
lifecycleItem.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@OverridepublicintgetTargetState(){returnON_RESUME;}@Retention(RetentionPolicy.SOURCE)public@interfaceLifecycleState{}publicstaticfinalintUNDEFINED=-1;publicstaticfinalintPRE_ON_CREATE=0;publicstaticfinalintON_CREATE=1;publicstaticfinalintON_START=2;publicstaticfinalintON_RESUME=3;publicstaticfinalintON_PAUSE=4;publicstaticfinalintON_STOP=5;publicstaticfinalintON_DESTROY=6;publicstaticfinalintON_RESTART=7;
可以看到ON_RESUME的值为3。接下来看cycleToPath源码:
privatevoidcycleToPath(ActivityClientRecord r,int finish,boolean excludeLastState,ClientTransaction transaction){//获取当前Activity的生命周期,即开始时的状态finalint 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函数的关键所在finalIntArray 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.javapublicIntArraygetLifecyclePath(int start,int finish,boolean excludeLastState){if(start ==UNDEFINED|| finish ==UNDEFINED){thrownewIllegalArgumentException("Can't resolve lifecycle path for undefined state");}if(start ==ON_RESTART|| finish ==ON_RESTART){thrownewIllegalArgumentException("Can't start or finish in intermittent RESTART state");}if(finish ==PRE_ON_CREATE&& start != finish){thrownewIllegalArgumentException("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);}elseif(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);}// Restart
mLifecycleSequence.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方法
*/privatevoidperformLifecycleSequence(ActivityClientRecord r,IntArray path,ClientTransaction transaction){//通过mHelper调用getLifecyclePath返回的path是ON_STARTfinalint 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){caseON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,null/* customIntent */);break;caseON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions,null/* activityOptions */);break;caseON_RESUME:
mTransactionHandler.handleResumeActivity(r,false/* finalStateRequest */,
r.isForward,"LIFECYCLER_RESUME_ACTIVITY");break;caseON_PAUSE:
mTransactionHandler.handlePauseActivity(r,false/* finished */,false/* userLeaving */,0/* configChanges */, mPendingActions,"LIFECYCLER_PAUSE_ACTIVITY");break;caseON_STOP:
mTransactionHandler.handleStopActivity(r,0/* configChanges */,
mPendingActions,false/* finalStateRequest */,"LIFECYCLER_STOP_ACTIVITY");break;caseON_DESTROY:
mTransactionHandler.handleDestroyActivity(r,false/* finishing */,0/* configChanges */,false/* getNonConfigInstance */,"performLifecycleSequence. cycling to:"+ path.get(size -1));break;caseON_RESTART:
mTransactionHandler.performRestartActivity(r,false/* start */);break;default:thrownewIllegalArgumentException("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
@Overridepublicvoidexecute(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
@OverridepublicActivityhandleLaunchActivity(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方法执行onCreatefinalActivity a =performLaunchActivity(r, customIntent);if(a !=null){
r.createdConfig =newConfiguration(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.java
privateActivityperformLaunchActivity(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 =newComponentName(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)){thrownewRuntimeException("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 =newConfiguration(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(newResourcesLoader[0]));
appContext.setOuterContext(activity);//调用attach方法,会在这个方法中创建Activity的PhoneWindow,并绑定对应的WindowManager
activity.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){thrownewSuperNotCalledException("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)){thrownewRuntimeException("Unable to start activity "+ component
+": "+ e.toString(), e);}}return activity;}
这个方法中的主要逻辑可以分为两部分,第一部分是实例化Activity,第二部分是执行Activity的onCreate的生命周期。先看第一部分,通过Instrumentation的newActivity获取到一个Activity实例,newActivity的参数传入了一个ClassLoader和Activity的className。因此,这里实例化Activity的过程一定是通过反射实现的。查看Instrumentation的newActivity方法如下:
publicActivitynewActivity(ClassLoader cl,String className,Intent intent)throwsInstantiationException,IllegalAccessException,ClassNotFoundException{String pkg = intent !=null&& intent.getComponent()!=null? intent.getComponent().getPackageName():null;returngetFactory(pkg).instantiateActivity(cl, className, intent);}privateAppComponentFactorygetFactory(String pkg){if(pkg ==null){Log.e(TAG,"No pkg specified, disabling AppComponentFactory");returnAppComponentFactory.DEFAULT;}if(mThread ==null){Log.e(TAG,"Uninitialized ActivityThread, likely app-created Instrumentation,"+" disabling AppComponentFactory",newThrowable());returnAppComponentFactory.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@NonNullActivityinstantiateActivity(@NonNullClassLoader cl,@NonNullString className,@NullableIntent intent)throwsInstantiationException,IllegalAccessException,ClassNotFoundException{return(Activity) cl.loadClass(className).newInstance();}
所以送上面代码可以知道在ActivityThread的performLaunchActivity 方法里面Instrumentation通过newActivity实例化了Activity,接着调用了Activity的attach方法。
@UnsupportedAppUsage(maxTargetSdk =Build.VERSION_CODES.R, trackingBug =170729553)finalvoidattach(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中持有PhoneWindow
mWindow =newPhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(mWindowControllerCallback);//将Activity自身设置到PhoneWindow
mWindow.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 =newVoiceInteractor(voiceInteractor,this,this,Looper.myLooper());}}//将PhoneWindow关联到WindowManager
mWindow.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中持有windowManager
mWindowManager = 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方法,代码如下:
publicvoidcallActivityOnCreate(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来执行的。其源码如下:
@OverridepublicvoidhandleStartActivity(ActivityClientRecord r,PendingTransactionActions pendingActions,ActivityOptions activityOptions){finalActivity activity = r.activity;if(!r.stopped){thrownewIllegalStateException("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进而执行onStart
activity.performStart("handleStartActivity");//将生命周期状态设置为on_start
r.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);}}elseif(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){thrownewSuperNotCalledException("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来执行的。
源码如下:
@OverridepublicvoidhandleResumeActivity(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;}finalActivity a = r.activity;if(localLOGV){Slog.v(TAG,"Resume "+ r +" started activity: "+ a.mStartedActivity
+", hideForNow: "+ r.hideForNow +", finished: "+ a.mFinished);}finalint 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){//获取PhoneWindow
r.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.}elseif(!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(newIdler());}
handleResumeActivity方法中的逻辑比较复杂,但核心主要有两点:
1、调用performResumeActivity执行onResume的生命周期
2、将DecorView添加到Window中。
先来看performResumeActivity方法其源码如下:
@VisibleForTestingpublicbooleanperformResumeActivity(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 falsereturnfalse;}if(r.getLifecycleState()==ON_RESUME){if(!finalStateRequest){finalRuntimeException e =newIllegalStateException("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,避免重复执行returnfalse;}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进而执行onResume
r.activity.performResume(r.startsNotResumed, reason);
r.state =null;
r.persistentState =null;//设置Activity的状态为ON_RESUME
r.setState(ON_RESUME);reportTopResumedActivityChanged(r, r.isTopResumedActivity,"topWhenResuming");}catch(Exception e){if(!mInstrumentation.onException(r.activity, e)){thrownewRuntimeException("Unable to resume activity "+ r.intent.getComponent().toShortString()+": "+ e.toString(), e);}}returntrue;}
在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()方法,具体代码如下:
voidstartProcessAsync(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可能出现的死锁finalMessage 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")finalProcessRecordstartProcessLocked(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方法
privateProcess.ProcessStartResultstartProcess(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");finalboolean 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.finalPackageManagerInternal pmInt = mService.getPackageManagerInternal();finalString[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
app.info.packageName, app.userId);finalString[] targetPackagesList = sharedPackages.length ==0?newString[]{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.finalSet<String> allowlistedApps =newArraySet<>(mAppDataIsolationAllowlistedApps);for(String pkg : targetPackagesList){
allowlistedApps.remove(pkg);}
allowlistedAppDataInfoMap =getPackageAppDataInfoMap(pmInt,
allowlistedApps.toArray(newString[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;}finalProcess.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(),newString[]{PROC_START_SEQ_IDENT+ app.getStartSeq()});}elseif(hostingRecord.usesAppZygote()){finalAppZygote 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,newString[]{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,newString[]{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方法,代码如下:
publicstaticProcessStartResultstart(@NonNullfinalString processClass,@NullablefinalString niceName,int uid,int gid,@Nullableint[] gids,int runtimeFlags,int mountExternal,int targetSdkVersion,@NullableString seInfo,@NonNullString abi,@NullableString instructionSet,@NullableString appDataDir,@NullableString invokeWith,@NullableString packageName,int zygotePolicyFlags,boolean isTopApp,@Nullablelong[] disabledCompatChanges,@NullableMap<String,Pair<String,Long>>
pkgDataInfoMap,@NullableMap<String,Pair<String,Long>>
whitelistedDataInfoMap,boolean bindMountAppsData,boolean bindMountAppStorageDirs,@NullableString[] zygoteArgs){returnZYGOTE_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方法。具体代码如下:
publicstaticvoidmain(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 certificatesfinalFile 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 =newActivityThread();//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是不能退出的,退出就无法接收事件了,一旦意外退出,就会抛出异常thrownewRuntimeException("Main thread loop unexpectedly exited");}
在main方法里面主要做了三件事:1、创建mainLooper,2、创建ActivityThread实例3、调用了attach方法。创建ActivityThread实例,同时会创建ApplicationThread实例,ApplicationThread实例是ActivityThread实例的属性。然后调用了attach方法:
@UnsupportedAppUsageprivatevoidattach(boolean system,long startSeq){
sCurrentActivityThread =this;
mConfigurationController =newConfigurationController(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的本地代理类finalIActivityManager 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(newRunnable(){@Overridepublicvoidrun(){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 =newInstrumentation();
mInstrumentation.basicInit(this);ContextImpl context =ContextImpl.createAppContext(this,getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true,null);
mInitialApplication.onCreate();}catch(Exception e){thrownewRuntimeException("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.finalConfiguration 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方法
@OverridepublicfinalvoidattachApplication(IApplicationThread thread,long startSeq){if(thread ==null){thrownewSecurityException("Invalid application interface");}synchronized(this){int callingPid =Binder.getCallingPid();finalint callingUid =Binder.getCallingUid();finallong origId =Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid, callingUid, startSeq);Binder.restoreCallingIdentity(origId);}}
在attachApplication方法中调用了attachApplicationLock()方法
/**
*该方法主要做了两件事:
1、调用ApplicationThread的bindApplication()方法去初始化Application,又是一次跨进程调用
2、通过makeActive方法赋值IApplicationThread
3、通过ATMS去启动目标Activity
*/@GuardedBy("this")privatebooleanattachApplicationLocked(@NonNullIApplicationThread 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;finalProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);if(pending !=null){
processName = pending.processName;}finalString 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){finalProcessRecord 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.}}returnfalse;}// 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);finalString processName = app.processName;try{AppDeathRecipient adr =newAppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr,0);
app.setDeathRecipient(adr);}catch(RemoteException e){
app.resetPackageList(mProcessStats);
mProcessList.startProcessLocked(app,newHostingRecord("link fail", processName),ZYGOTE_POLICY_FLAG_EMPTY);returnfalse;}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 later
app.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);finalBackupRecord 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));}finalActiveInstrumentation 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.finalString 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){finalAutofillManagerInternal 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){finalContentCaptureManagerInternal ccm =LocalServices.getService(ContentCaptureManagerInternal.class);if(ccm !=null){
contentCaptureOptions = ccm.getOptionsForPackage(app.userId,
app.info.packageName);}}SharedMemory serializedSystemFontMap =null;finalFontManagerInternal fm =LocalServices.getService(FontManagerInternal.class);if(fm !=null){
serializedSystemFontMap = fm.getSerializedSystemFontMap();}checkTime(startTime,"attachApplicationLocked: immediately before bindApplication");
bindApplicationTimeMillis =SystemClock.elapsedRealtime();
mAtmInternal.preBindApplication(app.getWindowProcessController());finalActiveInstrumentation instr2 = app.getActiveInstrumentation();if(mPlatformCompat !=null){
mPlatformCompat.resetReporting(app.info);}finalProviderInfoList 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());}elseif(instr2 !=null){//IPC操作,调用ApplicationThread的bindapplication去初始化Application
thread.bindApplication(processName, appInfo, providerList,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode ||!normalMode, app.isPersistent(),newConfiguration(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(),newConfiguration(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){//赋值IApplicationThread
app.makeActive(thread, mProcessStats);checkTime(startTime,"attachApplicationLocked: immediately after bindApplication");}updateLruProcessLocked(app,false,null);checkTime(startTime,"attachApplicationLocked: after updateLruProcessLocked");finallong 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 */);returnfalse;}// 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去启动Activity
didSomething = 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 */);returnfalse;}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():""));returntrue;}
在attachApplicationLocked方法中主要做了三件事:
1、调用IApplicationThread的bindApplication方法,IPC操作,创建绑定Application
2、通过makeActive方法赋值IApplicationThread
3、通过ATMS启动根Activity
先看makeActive方法:
@GuardedBy({"mService","mProcLock"})publicvoidmakeActive(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、创建Instrumentation
2、使用loadedApk创建一个application,不过最终还是使用的Instrumentation利用反射创建的Application类
3、使用Instrumentation初始化Application
**/@UnsupportedAppUsageprivatevoidhandleBindApplication(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 =newProfiler();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.finalString 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.finalInstrumentationInfo ii;if(data.instrumentationName !=null){
ii =prepareInstrumentation(data);}else{
ii =null;}finalContextImpl 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.finalIBinder b =ServiceManager.getService(Context.CONNECTIVITY_SERVICE);if(b !=null){finalConnectivityManager cm =
appContext.getSystemService(ConnectivityManager.class);Proxy.setHttpProxyConfiguration(cm.getDefaultProxy());}}finally{Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}if(!Process.isIsolated()){finalint 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 =newInstrumentation();
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;finalStrictMode.ThreadPolicy savedPolicy =StrictMode.allowThreadDiskWrites();finalStrictMode.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.//创建application
app = data.info.makeApplication(data.restrictedBackupMode,null);// Propagate autofill compat state
app.setAutofillOptions(data.autofillOptions);// Propagate Content Capture options
app.setContentCaptureOptions(data.contentCaptureOptions);sendMessage(H.SET_CONTENT_CAPTURE_OPTIONS_CALLBACK, data.appInfo.packageName);
mInitialApplication = app;finalboolean 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){thrownewRuntimeException("Exception thrown in onCreate() of "+ data.instrumentationName +": "+ e.toString(), e);}try{//调用application的onCreate方法
mInstrumentation.callApplicationOnCreate(app);}catch(Exception e){if(!mInstrumentation.onException(app, e)){thrownewRuntimeException("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{finalApplicationInfo info =getPackageManager().getApplicationInfo(
data.appInfo.packageName,PackageManager.GET_META_DATA/*flags*/,UserHandle.myUserId());if(info.metaData !=null){finalint 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)@OverridepublicbooleanattachApplication(WindowProcessController wpc)throwsRemoteException{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方法:
booleanattachApplication(WindowProcessController app)throwsRemoteException{boolean didSomething =false;for(int displayNdx =getChildCount()-1; displayNdx >=0;--displayNdx){
mTmpRemoteException =null;
mTmpBoolean =false;// Set to true if an activity was started.finalDisplayContent display =getChildAt(displayNdx);
display.forAllRootTasks(rootTask ->{if(mTmpRemoteException !=null){return;}if(rootTask.getVisibility(null/* starting */)==TASK_FRAGMENT_VISIBILITY_INVISIBLE){return;}finalPooledFunction 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 的启动流程图
版权归原作者 春晓 所有, 如有侵权,请联系我们删除。