xuexiansen / Gitxue

my blogs
0 stars 0 forks source link

startActivity启动分析 #1

Open xuexiansen opened 7 years ago

xuexiansen commented 7 years ago

1.概要

startActivity启动一个activity的源码分析,涉及概念较多,比如binder,aidl跨进程通信(ipc),栈管理概念;启动的时序图如下图(来自其他blog)所示: android 接下来基于sdk 23 源码里面看看,每个流程分别做了什么。主要分为 APP进程部分Server进程部分

2.APP进程(上)

2.1 Context,ApplicationThread(在ActivityThread里面),Instrumentation

首先启动一个页面可以,比如activity里面通过context.startActivity,会调用到startActivityForResult方法,接着会调用Instrumentation的execStartActivity方法,里面有几个入参需要注意的,第一个context自身,一个是ApplicationThread(它是一个binder本地对象,或者说是server对象,它是抽象类ApplicationThreadNative的实现类,具体能力的承载类,为后续AMS持有它的proxy进行启动activity使用),还有一个参数intent(传递参数);

2.2 ActivityManagerNative,ActivityManagerService(AMS),ActivityManagerProxy(asInterface,它入参就是从sm那里拿来的binder代理对象),ServiceManager,

ServiceManager只是一个装饰类,最终调用的方法是binder内核驱动的方法,是通过BinderInterner里获取的binder对象,如:addService,registerService等方法。它对应的也有serviceManagerNative等,所有的binder服务(AMS/PMS/)等都是从这边获取到对应client对象。 通过ActivityManagerProxy.startActivity,他的里面调用transact,接着通过binder IPC进入AMS;到此为止都是在APP进程中

3.Server进程

-------------------- Server进程部分 ------------------- 该部分主要是做一些启动前的校验,创建和管理Activity stack ,创建进程,绑定ApplicationThreadProxy.

3.1 AMN.onTransact

接下来我们就在, AMN是个抽象类,是个System server进程里面的本地服务,onTransact方法被调用,里面是真正的StartActivity方法的实现是在AMS中。

3.2 AMS.onTransact

在里面会调用startActivityAsUser,在SDK 23中是进入ActivityStackSupervisor,24中进入ActivityStarter的startActivityMayWait。

ActivityStackSupervisor 为了多屏而出现,管理多个ActivityStack

3.3 ASS.startActivityMayWait

这个方法的作用主要是获取ActivityInfo信息(如果有多个activity会弹框让用户选择),里面会经过PMS获取ActivityInfo信息,并保存在intent对象中,接着进入startActivityLocked,它的返回值里,如果大于等于0标识启动成功,小于零标识启动失败。

3.4 ASS.startActivityLocked

该方法会进行一系列的常规检查,比如activity是否在AndroidManifest注册,是否存在这个activity等等,常规检查通过之后,会进行权限的检查;如果在都成功的情况下,进行ActivityRecrd(一个Activity可以对应多个ActivityRecord)的创建;并校验App切换是否允许,如果不允许则要启动的Activity添加到pending中,并直接返回,相当于检查下是否又被阻塞的activity,优先启动。

3.5 ASS.startActivityUncheckedLocked (栈管理相关的操作)

这个阶段就不需要做些权限的检查;这个函数的主要作用就是找到或者创建新的Activity所属于的task对象,之后调用ActivityStack的startActivityLocked。其中会根据我的ActivityRecord的属性,从标签中获取,进行Standard、singleTop、singleTask、singleInstance相关要求的处理。比如是否需要新建栈,或者已有栈中是否存在此Activity,如果应用之前没有起来过,那找不到task如何处理等等。

如果不存在该Activity,则需要创建进入 ActivityStack(栈的管理,activity是否显示等等)

3.6 AS.startActivityLocked

入参里面,ActivityRecord,是否需要立马显示,是否需要创建新的task等等。 如果新启动一个app,表示宿主栈ActivityStack中没有历史任务,或者强制要求在新的任务中启动Activity, 既然是一个新任务,那么就需要需要将任务插入宿主栈顶。放入并放在栈顶之后,将Activity推入显示状态。

3.7 AS.resumeTopActivityLocked-> resumeTopActivityInnerLocked

找到第一个没有finishing的栈顶activity,找不到直接回到桌面,找到了,就执行startPausingLocked暂停activity,接着进入startSpecificActivityLocked.

3.8 AS.resumeTopActivityInnerLocked

尝试将ActivityRecord迁移到显示状态(Resumed),如果发现待显示的Activity的宿主进程可能没有启动,则需要回到ASS.startSpecificActivityLocked。

ActivityStackSupervisor

3.9 ASS. startSpecificActivityLocked

如果通过包名,发现才宿主进程不存在,则启动一个新的应用进程。这时候会调用AMS.newProcessRecord来创建一个新的ProcessRecord,然后再调用另外一个重载的AMS.startProcessLocked()函数,来创建一个进程。进入AMS.startProccesslocked。如果已经存在则直接进入realStartActivityLocked方法,进行启动activity。

ActivityManagerService

3.10 AMS.startProccesslocked (参考:http://gityuan.com/2016/10/09/app-process-create-2/)

简单就是发送一个消息,通知Zygote进程fork一个应用进程,同时会调用入口程序的ActivityThread的main方法,该方法中会初始化几个比较的变量,如ApplicationThread,looper,H。以及非常重要的AT.attach过程,通过binder, 调用到AMP-> AMS.attachApplication, 其参数mAppThread的数据类型为ApplicationThread,将ApplicationThreadProxy绑定到AMS。

到此为止: image

到此为止创建了待启动的Activity的宿主应用进程.

3.11 ASS.attachApplicationLocked

宿主进程如果创建好了,则调用realStartActivityLocked启动activity

4.APP进程(下)

-------------------- 回到APP进程部分 -------------------

4.1 ApplicationThreadProxy.scheduleLaunchActivity

通过IPC就会回到app进程中,ApplicationThreadProxy.scheduleLaunchActivity回调ActivityThreadNative.onTransact,从而进入ApplicationThread的scheduleLaunchActivity进行真正启动Activity

4.2 ApplicationThread. scheduleLaunchActivity

通过H (handler)sendMessage(H.LAUNCH_ACTIVITY),进入handleLaunchActivity

4.3 ApplicationThread. handleLaunchActivity

通过performLaunchActivity获取一个Activity对象(反射等),具体如4.4,然后执行队形的oncreate,onstart, onresume等生命周期

4.4 ApplicationThread. performLaunchActivity

该函数负责实际执行应用进程中Activity的启动,是系统进程调度启动一个Activity的落脚地,也就是Activity生命周期的开始地方。一个新的Activity对象,是通过反射创建的,所以需要包名、类名等信息,部分信息已经从系统进程传递到应用进程了,部分信息也都可以通过PackageManager再向系统进程索取;新建一个Activity对象。有了参数以后,便可以通过ClassLoader加载到Activity对应的类,反射构建之。同时Activity的Context、Theme会在Activity对象构建之后被初始化;接着就开始Actiivty的生命周期调用如onCreate,onStart

4.5 ApplicationThread.handleResumeActivity -> performResumeActivity

直至Activity处于显示状态。