基于Android10.0,分析startActivity的启动过程
一、概述
startActivity的整体流程和startService相近,启动后都是通过AMS来完成的。但相比service启动更加复杂,多了任务栈、UI、生命周期。其启动流程如下:
二、启动流程
启动Activity,一般是用startActivity。
2.1 Activity.startActivity
[->Activity.java]
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
2.2 startActivityForResult
[->ContextImpl.java]
1 | /** |
execStartActivity方法参数:
mAppThread:类型为ApplicationThread,通过mMainThread.getApplicationThread()获取。
mToken:为Binder类型
2.3 execStartActivity
[->Instrumentation.java]
1 | public ActivityResult execStartActivity( |
2.3.1 AM.getService
和Android6.0不同的是Android10.0直接通过AIDL的方式生成了AMS的代理。
1 | /** |
2.4 IActivityManager.startActivity
通过AIDL生成的代理类调用AMS的startActivity,其代理类在编译的时候,会自动生成。
startActivity共有10个参数,参数对应值如下:
- caller:当前应用的Application对象mAppThread
- callingPackage:当前Activity所在的包名
- intent:启动Activity传过来的参数
- resolvedType:调用intent.resolveTypeIfNeeded获取
- resultTo:来自当前Activity.mToken
- resultWho: 来自当前Activity.mEmbeddedID
- requestCode:-1
- startFlags:0
- profilerInfo:null
- bOptions:null
2.5 AMS.startActivity
[->ActivityManagerService.java]
1 | @Override |
2.6 AMS.startActivityAsUser
[->ActivityManagerService.java]
1 | public final int startActivityAsUser(IApplicationThread caller, String callingPackage, |
通过建造者模式,来设置参数,其参数在2.4节有介绍,通过execute方法最后执行。
2.6.1 ASC.obtainStarter
[->ActivityStartController.java]
1 | /** |
2.6.2 AS.setMayWait
这个方法在2.6.3节中用到,可以看到这里将mRequest.mayWait设置为true
1 | ActivityStarter setMayWait(int userId) { |
2.6.3 AS.execute
[->ActivityStarter.java]
1 | /** |
2.7 AS.startActivityMayWait
这个方法的参数有21个,具体重要的几个参数2.4节已经介绍过, inTask = null。
[->ActivityStarter.java]
1 | private int startActivityMayWait(IApplicationThread caller, int callingUid, |
2.7.1 PKMS.resolveIntent
[->PackageManagerService.java]
mSupervisor.resolveInten经过层层调用,通过IPC最后会调用PKMS对象中的resolveIntent。
1 | /** |
2.7.2 ASS.resolveActivity
[->ActivityStackSupervisor.java]
1 | ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags, |
Activity类有3个flags用于调试
- START_FLAG_DEBUG:用于调试debug app
- START_FLAG_NATIVE_DEBUGGING:用于调试native
- START_FLAG_TRACK_ALLOCATION:用于调试allocation tracking
2.8 AS.startActivity
[->ActivityStarter.java]
1 | private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, |
下面才正式进入startActivity具体内容
1 | private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, |
在上面这三个返回值表示启动activity失败
START_INTENT_NOT_RESOLVED:从intent中无法找到相应的component
START_CLASS_NOT_FOUND :从intent中无法找到相应的ActivityInfo
START_NOT_VOICE_COMPATIBLE :不支持voice task
1 | private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, |
2.8.1 AMS.checkAppSwitchAllowedLocked
[->ActivityManagerService.java]
1 | boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid, |
当mAppSwitchesAllowedTime时间小于当前时间或者具有STOP_APP_SWITCHES的权限,则允许app发生切换操作。 其中mAppSwitchesAllowedTime在AMS.stopAppSwitches的过程中会设置, mAppSwitchesAllowedTime = SystemClock.uptimeMillis()+APP_SWITCH_DELAY_TIME(=5s); 禁止app切换的timeout时间为5s。
当发送5s超时或者执行ASM.resumeAppSwitches过程会将mAppSwitchesAllowedTime 设置为0,都会开启允许app执行切换的操作。禁止app切换的操作,对于同一个app是不受影响的,可查看AMS.checkComponentPermission
2.8.1 ASC.doPendingActivityLaunches
[->ActivityStartController.java]
1 | void doPendingActivityLaunches(boolean doResume) { |
mPendingActivityLaunches记录所有将要启动的Activity,由于在startActivity过程中时app切换功能被禁止,也就是不运行切换的Activity,就会将该Activity加入到mPendingActivityLaunches队列,该队列执行完doPendingActivityLaunches会清空。启动doPendingActivityLaunches的所有Activity,由于doResume=false,那么activity不会进入resume,而是设置delayedResume = true,延迟resume。
2.9 AS.startActivityUnchecked
[->ActivityStarter.java]
1 | //r是本次要启动的activity,sourceRecord是调用者 |
找到或者创建新的Activity所属的Task对象,之后调用AS.startActivityLocked
2.9.1 AS.setInitialState
[->ActivityStarter.java]
1 | private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask, |
2.9.2 AS.computeLaunchingTaskFlags
[->ActivityStarter.java]
1 | private void computeLaunchingTaskFlags() { |
2.9.3 AS.computeSourceStack
[->ActivityStarter.java]
1 | private void computeSourceStack() { |
2.9.4 AS.getReusableIntentActivity
[->ActivityStarter.java]
1 | /** |
上面是根据不同的启动模式,来获取ActivityRecord信息,来决定将要启动的activity所在的栈。
2.9.5 Launch Mode
AcitivityInfo.java定义了四类Launch Mode:
1 | /** |
常见的flag含义
FLAG_ACTIVITY_NEW_TASK
将新Activity放入新启动的task。
FLAG_ACTIVITY_CLEAR_TASK
启动Activity时,将目标Activity关联的task清除,再启动新task,将该Activity放入该Task。这个flag一般配置FLAG_ACTIVITY_NEW_TASK使用。
FLAG_ACTIVITY_CLEAR_TOP
启动非栈顶Activity时,先清除该Activity之上的Activity. 例如Task已有A,B,C,D,启动A,则需要先清除B,C,D,类似SingleTop。
2.10 AS.startActivityLocked
[->ActivityStack.java]
1 | void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, |
2.11 ASS.resumeFocusedStackTopActivityLocked
[->ActivityStackSupervisor.java]
1 | boolean resumeFocusedStackTopActivityLocked( |
2.12 AS.resumeTopActivityUncheckedLocked
[->ActivityStack.java]
1 | boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { |
2.13 AS.resumeTopActivityInnerLocked
[->ActivityStack.java]
1 | @GuardedBy("mService") |
主要工作如下:
- 当找不到resume的activity时,则直接回到桌面
- 当resume状态activity不为空,则执行startPausingLocked,暂停该Activity
- 当Activity之前启动过,则直接resume,否则执行startSpecificActivityLocked,2.14节将继续讨论。
2.13.1 AS.resumeTopActivityInNextFocusableStack
[->ActivityStack.java]
1 | private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev, |
当找不到需要的resume的Activity时,直接回到桌面
2.13.2 AS.pauseBackStacks
[->ActivityStack.java]
1 | /** |
暂停所有处于后台栈的所有Activity
2.13.3 AS.startPausingLocked
[->ActivityStack.java]
1 | final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, |
通过LifecycleManager的方式来暂停Activity操作。对于pauseImmediately= true则执行completePauseLocked操作,否则等待app通知500ms超时再执行该方法。
2.13.4 AS.completePauseLocked
[->ActivityStack.java]
1 | private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) { |
暂停Activity完成后,修改暂停activity状态
2.14 ASS.startSpecificActivityLocked
[->ActivityStackSupervisor.java]
1 | void startSpecificActivityLocked(ActivityRecord r, |
2.15 AMS.startProcessLocked
这个过程为启动Android进程的过程,在文章Android进程启动过程解析,详细描述了startProcessLocked整个过程,创建完成新进程之后,在新进程中通过binder ipc方式后调用到AMS.attachApplicationLocked。
[->ActivityManagerService.java]
1 | private final boolean attachApplicationLocked(IApplicationThread thread, |
在bindApplication后,调用了ASS.attachApplicationLocked。
2.16 ASS.attachApplicationLocked
[->ActivityStackSupervisor.java]
1 | boolean attachApplicationLocked(ProcessRecord app) throws RemoteException { |
2.17 ASS.realStartActivityLocked
[->ActivityStackSupervisor.java]
1 | final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, |
Android9.0之后,引入了ClientLifecycleManager和ClientTransactionHandler来辅助管理Activity的生命周期。
一个生命周期都抽象出了一个对象。
onCreate (LaunchActivityItem),onResume(ResumeActivityItem),
onPause(PauseActivityItem),onStop(StopActivityItem),onDestrory(DestroyActivityItem)
2.18 CLM.scheduleTransaction
[->ClientLifecycleManager.java]
将2.17节启动Activity生命周期的代码单独分析一下启动的过程
1 | //创建Activity启动事务 |
2.18.1 AMS.getLifecycleManager
[->ActivityManagerService.java]
1 | ClientLifecycleManager getLifecycleManager() { |
2.18.2 CLM.scheduleTransaction
[->ClientLifecycleManager.java]
1 | void scheduleTransaction(ClientTransaction transaction) throws RemoteException { |
2.18.3 CT.schedule
[->ClientTransaction.java]
1 | public IApplicationThread getClient() { |
2.18.4 AT.scheduleTransaction
[->ActivityThread.java]
1 | @Override |
ActivityThread继承ClientTransactionHandler
[->ClientTransactionHandler.java]
1 | /** Prepare and schedule transaction for execution. */ |
2.18.5 AT.handleMessage
[->ActivityThread.java]
1 | public void handleMessage(Message msg) { |
2.18.6 TE.execute
[->TransactionExecutor.java]
1 | /** |
[->TransactionExecutor.java]
1 | public void executeCallbacks(ClientTransaction transaction) { |
[->LaunchActivityItem.java]
1 | @Override |
2.18.7 TE.cycleToPath
[->TransactionExecutor.java]
1 | /** |
cycleToPath将会执行从start,finish之间的周期方法。
2.19 AT.handleLaunchActivity
[->ActivityThread.java]
1 | /** |
2.20 AT.performLaunchActivity
[->ActivityThread.java]
1 | private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { |
2.21 callActivityOnCreate
[->Instrumentation.java]
1 | public void callActivityOnCreate(Activity activity, Bundle icicle) { |
2.22 performCreate
[->Activity.java]
1 | @UnsupportedAppUsage |
到此,介绍了完成了Activity从onCreate,onStart,onResume的生命周期详细过程。
三、总结
本文从startActivity开始,详细分析了Activity的启动过程。
- 流程[2.1~2.3]:运行在调用者的进程当中,比如桌面启动Activity,则调用者所在的进程为launcher,launcher进程通过IActivityManager.aidl生成的代理类,进入到了systemserver进程(AMS相应的Server端)。
- 流程[2.3~2.17]:允许在systemserver系统进程中,这个过程为比较复杂且核心的过程,主要如下:
- 流程[2.7]:调用resolveActivity,通过PackageManager查询系统中所有符合要求的Activity,当存在多个满足多个条件的Activity则会让用户来选择 。
- 流程[2.8]:创建ActivityRecord对象,检查intent相关信息和权限,是否允许app切换,然后处理mPendingActivityLaunches中的Activity
- 流程[2.9]:为Activity找到或创建新的Task对象,设置flags信息
- 流程[2.13]:当没有处于任务栈中没有Activity时,直接回到桌面了;否则当mResumeActivity不为空是,先执行startPausingLocked方法暂停该Activity,然后进入startSpecificActivityLocked
- 流程[2.14]:当目标进程已经存在则直接进入2.17,当目标进程不存在时则创建进程,经过调用最后到2.17
- 流程[2.17]:systemserver进程通过IApplicationThread binder接口,进入到了目标进程。
- 流程[2.18~2.20]:允许在目标进程,通过Handler消息机制,该进程中的binder线程向主线程发送EXECUTE_TRANSACTION消息,进入事务处理阶段调用到handleLaunchActivity,最后通过发射创建的目标Activity,然后进入到onCreate生命周期。
从进程的角度分析
- 点击桌面图标,Launcher进程采用Binder IPC向systemserver进程发送startActivity请求
- systemserver进程接收到请求后,向zygote进程发送创建进程的请求
- zygote进程fork出新的子进程即app进程
- App进程,通过Binder IPC向systemserver进程发起attachApplication请求
- systemserver进程收到请求后,进行一系列准备工作后,在通过binderIPC进程发送scheduleTransaction请求
- APP进程的binder进程(ApplicationThread)在收到请求后,通过handler向主线程发送EXECUTE_TRANSACTION消息。
- 主线程收到Message消息后,通过反射机制创建目标Activity,并回调Activity的onCreate方法。
到此应用正式启动,开始进入应用的生命周期,执行完onCreate,onStart,onResume方法,makeVisible,UI渲染结束后就可以看到App的主界面了。
附录
源码路径
1 | frameworks/base/core/java/android/content/ContextWrapper.java |