初学安卓framework系列 四 (系统中的那些进程)

打开android studio,你可以看到在logcat工具栏有一个process的下拉菜单,打开之后可以看到当前安卓设备的所有进程

Screenshot 2023-02-20 at 9.40.04 PM.png

除了安装的第三方app之外,会有很多系统自带的进程,最重要的莫过于system server所在的process,长这个样子

Screenshot 2023-02-20 at 9.44.49 PM.png

今天我打算用一章节来稍微聊聊安卓中的进程,内容包括:

  1. 安卓中的系统进程的位置
  2. 安卓system server启动系统进程的阶段phase
  3. 共享进程

各个进程的代码在哪?

安卓最重要的系统进程当然是system_process. 这个进程是zygote孵化的第一个进程,它管理着安卓系统中各种大大小小的系统service的实现(SystemService)。也就是下面图中各种manager的server端实现(安卓的C/S 架构)。

android_layers-1.jpg

除此之外,其他的系统进程很多处于这个位置:

platform/packages/

以apps开头的肯定都是独立的1st party app。以services开头的某些是独立进程。

比如Telephony进程,它的名字对应安卓中的phone进程 (看它的manifest文件)

Screenshot 2023-02-20 at 10.02.08 PM.png

打开logcat也可以看到这个进程

Screenshot 2023-02-20 at 10.02.36 PM.png

有些是和其他package共享进程的,比如Telecom.

Screenshot 2023-02-20 at 10.05.54 PM.png

可以看到这个进程和另外一个叫system的进程share user id,他们最终会进入到同一个进程中。而这个system进程就是大名鼎鼎的system_process....

android.googlesource.com/platform/fr…

Screenshot 2023-02-20 at 10.10.36 PM.png

也就是说,Telephony和Telecom这两个package虽然是独立的package(从代码的分布来说,但是在运行时跑在不同的进程,而且两个package一个是拥有自己的独立进程,另一个会最终跑在系统服务进程。

Screenshot 2023-02-20 at 10.13.04 PM.png

打开logcat,filter到system_process进程的log,你可以搜到Telecom的log。证明Telecom这个package的确是跑在系统进程上了。

系统进程的启动

system_process作为第一个孵化出来的java service进程,除了要负责启动在system_process里面的系统服务之外

比如:

android.googlesource.com/platform/fr…

Screenshot 2023-02-21 at 9.30.17 PM.png

PS:android开发团队自己也觉得这样hardcode service name不太好, 想通过读取系统构建的某些文件来做。。。但是一直没改 :( 。

还需要启动的其他的系统进程。

当系统进程的关键性服务都启动好了之后,ActivityManagerService就会开始启动被标记为direct boot aware 的进程,中文叫直接启动模式

当设备已开机但用户尚未解锁设备时,Android 7.0 将在安全的“直接启动”模式下运行

Screenshot 2023-02-21 at 9.48.52 PM.png

要让当前进程(package )成为直接启动模式的进程, 只需要像上面截图一样把directBootAware 标记为true就行了。

ActivityManagerService在系统进程启动完毕所有的必要service之后,就开始启动direct boot aware的package了。

android.googlesource.com/platform/fr…

Screenshot 2023-02-21 at 9.52.04 PM.png

比如上文介绍到的Telephony package就是被标记成一个direct boot aware的app。

android.googlesource.com/platform/pa…

这里有个文档的坑,要想一个app成为直接启动模式的app(也就是Application class oncreate会被调用)的话还需要多加一个persistent=true的标记。但是文档里面没有详细写。。。。

Screenshot 2023-02-21 at 9.58.42 PM.png

这个package的application class会在系统服务启动结束之后马上被创建,onCreate会被调用

Screenshot 2023-02-21 at 9.59.10 PM.png

所以在安卓启动的过程中,有三个重要的阶段

  1. 启动系统进程服务阶段, critical service phase
  2. 启动完step 1,开始启动其他重要的进程,但是在用户还没解锁屏幕之前,这个阶段叫direct boot phase. 这个阶段启动的进程都是用户在没有解锁屏幕之前能做的,比如说打紧急电话.(所以Telephony进程必须在direct boot 阶段启动)
  3. 用户解锁结束,这个阶段叫boot complete phase

共享进程的package

上面介绍过某些package可以共享进程。比如Telecom的代码明明有自己独立的manifest,还有自己独立的package name

package="com.android.server.telecom"
复制代码

但是最后其实代码还是跑在system_process里面。

原因是在管理所有系统进程的类ProcessList里面,当要启动的package是系统进程的时候,安卓会在已经launch的进程中选择第一个作为系统进程的那个process。

Screenshot 2023-02-22 at 9.08.12 PM.png

所以简单来总结一下,安卓系统在启动过程中做了如下几件事情

Screenshot 2023-02-22 at 9.23.25 PM.png

安卓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,在代码中进行全局搜索就行了。

猜你喜欢

转载自juejin.im/post/7203180600819744827