打开android studio,你可以看到在logcat工具栏有一个process的下拉菜单,打开之后可以看到当前安卓设备的所有进程
除了安装的第三方app之外,会有很多系统自带的进程,最重要的莫过于system server所在的process,长这个样子
今天我打算用一章节来稍微聊聊安卓中的进程,内容包括:
- 安卓中的系统进程的位置
- 安卓system server启动系统进程的阶段phase
- 共享进程
各个进程的代码在哪?
安卓最重要的系统进程当然是system_process. 这个进程是zygote孵化的第一个进程,它管理着安卓系统中各种大大小小的系统service的实现(SystemService)。也就是下面图中各种manager的server端实现(安卓的C/S 架构)。
除此之外,其他的系统进程很多处于这个位置:
以apps开头的肯定都是独立的1st party app。以services开头的某些是独立进程。
比如Telephony进程,它的名字对应安卓中的phone进程 (看它的manifest文件)
打开logcat也可以看到这个进程
有些是和其他package共享进程的,比如Telecom.
可以看到这个进程和另外一个叫system的进程share user id,他们最终会进入到同一个进程中。而这个system进程就是大名鼎鼎的system_process….
android.googlesource.com/platform/fr…
也就是说,Telephony和Telecom这两个package虽然是独立的package(从代码的分布来说,但是在运行时跑在不同的进程,而且两个package一个是拥有自己的独立进程,另一个会最终跑在系统服务进程。
打开logcat,filter到system_process进程的log,你可以搜到Telecom的log。证明Telecom这个package的确是跑在系统进程上了。
系统进程的启动
system_process作为第一个孵化出来的java service进程,除了要负责启动在system_process里面的系统服务之外
比如:
android.googlesource.com/platform/fr…
PS:android开发团队自己也觉得这样hardcode service name不太好, 想通过读取系统构建的某些文件来做。。。但是一直没改 🙁 。
还需要启动的其他的系统进程。
当系统进程的关键性服务都启动好了之后,ActivityManagerService就会开始启动被标记为direct boot aware 的进程,中文叫直接启动模式。
当设备已开机但用户尚未解锁设备时,Android 7.0 将在安全的“直接启动”模式下运行
要让当前进程(package
)成为直接启动模式的进程, 只需要像上面截图一样把directBootAware 标记为true就行了。
ActivityManagerService在系统进程启动完毕所有的必要service之后,就开始启动direct boot aware的package了。
android.googlesource.com/platform/fr…
比如上文介绍到的Telephony package就是被标记成一个direct boot aware的app。
android.googlesource.com/platform/pa…
这里有个文档的坑,要想一个app成为直接启动模式的app(也就是Application class oncreate会被调用)的话还需要多加一个persistent=true的标记。但是文档里面没有详细写。。。。
这个package的application class会在系统服务启动结束之后马上被创建,onCreate会被调用
所以在安卓启动的过程中,有三个重要的阶段
- 启动系统进程服务阶段, critical service phase
- 启动完step 1,开始启动其他重要的进程,但是在用户还没解锁屏幕之前,这个阶段叫direct boot phase. 这个阶段启动的进程都是用户在没有解锁屏幕之前能做的,比如说打紧急电话.(所以Telephony进程必须在direct boot 阶段启动)
- 用户解锁结束,这个阶段叫boot complete phase
共享进程的package
上面介绍过某些package可以共享进程。比如Telecom的代码明明有自己独立的manifest,还有自己独立的package name
package="com.android.server.telecom"
但是最后其实代码还是跑在system_process里面。
原因是在管理所有系统进程的类ProcessList里面,当要启动的package是系统进程的时候,安卓会在已经launch的进程中选择第一个作为系统进程的那个process。
所以简单来总结一下,安卓系统在启动过程中做了如下几件事情
安卓framework中的面向对象
最后提一嘴,安卓framework代码中的面向对象设计做得很好。基本上所有的现实中的实例都有在代码中一一对应。
比如设备中每一个package在代码中抽象成PackageInfo.java
, 这个类中所有的field都一一对应着一个安卓package manifest 文件中的tag。比如android:sharedUserId,就是一个PackageInfo.java
中 的 public String sharedUserId;
再比如一个进程,在安卓的framework中的java代码也就叫Process.java ,启动进程,杀死进程等等操作都被抽象成Process.java中的API (比如启动当前进程 -> 对应Process#start()
方法 )
这些抽象对开发者或者源代码阅读者都带来了极大的便利。比如想查找某一个manifest的tag是怎么被使用的,可以打开PackageInfo.java
类,搜索该tag在类中对应的field,在代码中进行全局搜索就行了。