Android进程生命周期
bootloader引导启动内核后,内核作为pid=0的0号进程,fork出kthreadd和init两个进程。其中kthreadd是所有内核进程的祖宗,init是所有用户进程的祖宗。init fork出Zygote,这是所有Java进程的祖宗。
kernel找init的顺序是:
- bootargs是否有指定init
- /init
- /bin/init;/sbin/init;/etc/init
- /bin/sh
init启动后,做以下几件事情:
- 处理init.rc
- 启动监听服务
- 属性监听
- 子进程退出信号(SIGCHLD)监听
init.rc 由一个个 section 组成, 每一个 section 定义了一个 Action, 或者一个 Service。 Action 由 trigger 和 一组 command 组成。trigger 表示触发这个 Action 的条件, command 表示这个 Action 被触发后所执行的一系列动作。 Service 描述了一个服务的名字,执行路径,启动参数等信息。还可以通过 option 来约定服务的一些行为,权限等。比如是否只启动一次,服务进程的 uid, gid等。
init.rc 的所有语法介绍都可以在 Android/system/core/init/README.md 这个文件里面查找到
更多init.rc内容,可查阅 https://qiushao.net/2020/03/01/Android%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E8%BF%9B%E9%98%B6/init.rc%E4%BB%8B%E7%BB%8D/
也可通过trigger命令触发执行,如下图:
当init解析完init.rc后,会触发执行
- on early-init
- on init
- on late-init
- on property
- service
属性监听:
- getprop命令获取当前所有属性
- setprop key value设置属性
- 通过/dev/socket/property_service socket来监听属性事件
子进程退出信号(SIGCHLD)监听:
- 如果service没有配置为oneshot,则当子进程异常退出时,init会重新启动该进程
可以通过setprop ctl.start ctl.stop 来启动或暂停某个指定服务 如setprop ctl.stop p2p_supplicant
servicemanager的特殊身份,导致如果servicemanager重启,配套的很多其他service也需要重启。
https://www.protechtraining.com/static/slides/Deep_Dive_Into_Binder_Presentation.html#slide-13
zygote 与 systemserver
https://www.codecentric.de/wissens-hub/blog/android-zygote-boot-process
Android进程管理核心组件
- ServiceManager
- ActivityManagerService
- ActivityThread
- ApplicationThread
Activity的组织
- ActivityStackSupervisor
- ActivityStack
- TaskRecord
- ActivityRecord
通过命令dumpsys activity 查看四大组件上述 信息。
dumpsys activity activities查看activity的信息。
AndroidManifest.xml中可以通过组件的taskAffinity属性设置taskRecord名称。 通过android:process属性设置新的进程名称。
fork因为在多线程下可能导致死锁的局限性,如果zygote使用binder机制进行通信,当zygote调用fork时,可能会有死锁问题。故zygote不采用binder机制通信,而选择socket通信。
当zygote要启动新进程时,会使用抛出MethodAndArgsCaller的异常,而不是直接调用fork启动新进程,是因为如果直接调用fork会导致函数调用栈非常长,抛异常到顶层去fork,可以解决这个问题。
启动新Activity进程的流程
- 某个activity调用startActivity
- 通过binder将消息发给ActivityManagerService
- ActivityManagerService调用startActivityMayWait向ActivityStackSupervisor查询
- ActivityStackSupervisor调用startActivityLocked向ActivityStack查询
- ActivityStack返回startProcessLocked
- ActivityManagerService调用Process类的startViaZygote 方法,通过socket向Zygote发送新建进程(android.app.ActivityThread)的消息
- Zygote通过ZygoteInit抛出一个ZygoteInit.MethodAndArgsCaller异常启动一个新的ActivityThread
- ActivityThread 跑起来Looper/H(Handler)
- ActivityThread创建一个ApplicationThread
- ActivityThread通过attachApplication向ActivityManagerService发起绑定请求
- ActivityManagerService通过bindApplication绑定新进程
- ApplicationThread将绑定请求转发给同进程Looper,由Looper进行handleBindApplication处理
- 至此一个新的application已创建完成,此application即为AndroidManifest文件里的application
- (每个application是和进程绑定的,可以通过override Application的onCreate方法来实现当新进程创建时的初始化操作。)
- ActivityManagerService会调用attachApplicationLocked通知ActivityStackSupervisor
- ActivityStackSupervisor通过scheduleLaunchActivity发送给新进程的ApplicationThread,启动一个新的activity
- ApplicationThread将请求转发给同进程Looper,由Looper进行handleLaunchActivity处理,启动新Activity,并调用onCreate/onStart方法
启动新Service进程的流程
结构
- ActivityManagerService
- ActiveServices
- ServiceRecord
启动service有两种方式
- 通过调用startService方法启动service,这种情况下,即使调用startService的进程退出,service也依旧存在。
- 通过binder机制启动service,当发送解绑时,service会退出。
startService方法启动service
- Activity 调用startService,向ActivityManagerService发起新建service请求
- ActivityManagerService调用startServiceLocked咨询ActiveServices
- ActiveServices发现要新建进程,返回startProcessLocked
- ActivityManagerService调用Process类的startViaZygote 方法,通过socket向Zygote发送新建进程(android.app.ActivityThread)的消息
- Zygote通过ZygoteInit抛出一个ZygoteInit.MethodAndArgsCaller异常启动一个新的ActivityThread
- ActivityThread 跑起来Looper/H(Handler)
- ActivityThread创建一个ApplicationThread
- ActivityThread通过attachApplication向ActivityManagerService发起绑定请求
- ActivityManagerService通过bindApplication 绑定新进程
- ApplicationThread将绑定请求转发给同进程Looper,由Looper进行handleBindApplication处理
- ActivityManagerService通过attachApplicationLocked通知ActiveServices
- ActiveServices调用scheduleCreateService通知ApplicationThread
- ApplicationThread将消息转发给同进程Looper
- Looper调用handleCreateService启动新的service,触发onCreate,onStartCommand方法的调用,在onStartCommand方法的调用完成后,service即进入工作状态。
bindService方法启动service
- Application A向LoadedApk类获取getServiceDispatcher
- 调用getServiceDispatcher获取Service Connection的binder接口
- App A向AMS发送bindService请求,附带Service Connection对象
- … AMS 启动目标Service
- ActiveServices向Service 发送scheduleBindService请求
- Service Application触发onBind方法,返回service接口的binder封装
- ActivityThread向AMS publishService发布服务接口,带上service接口的binder封装
- AMS通过ActiveServices调用onServiceConnected调用Service Connection的方法,将service接口的binder封装传给Application A的进程空间。
- 接下来Application A可以像调用本地接口一样调用另一个Application Service的接口。
ContentProvider的创建流程
- Content Resolver是Application A的本地content provider代理
- 当Activity CRUD Content Resolver时,Content Resolver会向AMS请求getContent Provider
- … AMS启动新的Content Provider Application
- 新的Application会遍历manifest文件里的content provider,执行installContentProviders,触发执行onCreate方法
- 新Application调用getIContentProvider获取provider的binder封装
- 通过publishContentProviders将provider的binder封装对象发给AMS
- AMS调用newHolder将Provider的binder对象发给ContentProviderRecord
- ContentProviderRecord生成一个新的封装,并返回给Content Resolver
- 至此,Application A的进程空间,多出一个Provider binder封装的对象,可直接调用provider的接口。
BroadcastReceiver的创建流程
设备启动时,Packager MangerService会遍历所有包,将所有reciver通过addActivity注册到ActivityIntentResolver中
- Activity向AMS发起广播,并附带broadcastIntent
- AMS向Packager ManagerService发起queryIntentReceivers请求
- Packager ManagerService返回哪些Receiver可以处理该广播
- AMS将获取到的信息通过enqueueOrderedBroadcast推到BroadcastQueue队列
- BroadcastQueue通过handleMessage推给BroadcastHandler处理
- BroadcastHandler调用deliverToRegisteredReceiverLocked将消息传给目标receiver应用
- 如果发现对于receiver的进程没启动,则返回给AMS startProcessLocked
- … AMS启动新进程,准备好receiver运行环境
- BroadcastQueue向service所在ApplicationThread发送scheduleReceiver消息
- ApplicationThread将消息转给同进程Looper处理
- Looper调用handleReceiver,调用onReceive方法
- receiver进程会持续存在,但是每次新的广播来时,都会新建一个receiver实例
TODO property 存储在哪里?