系统服务¶
正如我们在上一节看到的,系统服务器是作为 Zygote 启动的一部分而启动的,我们将在本节继续深入探讨这个过程。然而,正如第 2 章所讨论的,也有从系统服务器以外的进程启动的系统服务,我们将在本节讨论这些。
从 4.0/Ice-Cream Sandwich 开始,第一个启动的系统服务是 Surface Flinger。在 2.3/Gingerbread 及之前,它一直是作为系统服务器的一部分启动的,但到了 4.0/Ice-Cream Sandwich,它在 Zygote 之前就已启动,独立于系统服务器和其他系统服务运行。以下是 4.2/Jelly Bean 的 init.rc 中 Zygote 条目之前的相关片段:
service surfaceflinger /system/bin/surfaceflinger
class main
user system
group graphics drmrpc
onrestart restart zygote
Surface Flinger 的源码在 2.3/Gingerbread 的 frameworks/base/services/surfaceflinger/ 和 4.2/Jelly Bean 的 frameworks/native/services/surfaceflinger/ 中。它的作用是将应用使用的绘图表面(drawing surfaces)合成为显示给用户的最终图像。因此,它是 Android 最基本的构建块之一。
在 Android 4.0 中,由于 Surface Flinger 在 Zygote 之前启动,系统的启动动画比以前版本出现得更快。我们将在本章稍后讨论启动动画。
为了启动系统服务器,Zygote fork 并运行 com.android.server.SystemServer 类的 main() 函数。后者加载包含部分系统服务所需 JNI 部分的 libandroid_servers.so 库,然后调用 frameworks/base/cmds/system_server/library/system_init.cpp 中的原生代码,启动在 system_server 进程中运行的 C 代码系统服务。在 2.3/Gingerbread 中,这包括 Surface Flinger 和传感器服务(Sensor Service)。然而在 4.2/Jelly Bean 中,Surface Flinger 是单独启动的(正如我们刚刚看到的),而由 system_server 启动的唯一 C 代码系统服务是传感器服务。
然后系统服务器回到 Java 领域,开始初始化关键的系统服务,如电源管理器(Power Manager)、活动管理器和包管理器。随后继续初始化它托管的所有系统服务,并将它们注册到服务管理器中。这一切都是在 frameworks/base/services/java/com/android/server/SystemServer.java 的代码中完成的。这一切都是不可配置的。它被硬编码到 SystemServer.java 中,没有你可以传递的标志或参数来告诉系统服务器不启动某些系统服务。如果你想禁用任何一个,就必须亲自动手注释掉相应的代码。
系统服务之间是相互依赖的,Android 的几乎所有部分——包括 Android API——都假设所有内置于 AOSP 的系统服务始终可用。正如我在第 2 章提到的,系统服务整体上构成了构建在 Linux 之上的面向对象操作系统——而且这个操作系统的各个部分并不是为模块化而构建的。因此,如果你去掉其中一个系统服务,Android 的某些部分很可能就会开始出现故障。
但这并不意味着不能做到。作为 2012 年 Android Builders Summit 上一个题为"无头 Android"(Headless Android)演讲的一部分,我展示了我如何成功禁用了 Surface Flinger、窗口管理器(Window Manager)和其他几个关键系统服务,从而在无头系统上运行完整的 Android 栈。正如我在那次演讲中警告的那样,这项工作在很大程度上是一个概念验证,如果要达到生产就绪,还需要更多的努力。
因此,尽管去折腾吧,但你已经被警告了——如果你要在 Android 的核心深处玩这么深,最好做好准备。
/system/bin/system_server 是什么?¶
你可能在浏览目标的根文件系统时注意到,/system/bin 中有一个名为 system_server 的二进制文件。然而,这个二进制文件与系统服务器的启动或任何系统服务都无关。目前尚不清楚这个二进制文件有什么用途(如果有的话)。这很可能是 Android 早期的遗留工具。
这个事实往往是混淆的来源,因为快速查看二进制文件列表和 ps 输出可能会让你相信 system_server 进程实际上是由 system_server 命令启动的。我实际上对自己阅读源码的结果持怀疑态度,并在 android-building 邮件列表上发布了相关问题。然而,后续的回复似乎证实了我自己对源码的理解。
mediaserver¶
除了 Surface Flinger 和系统服务器启动的系统服务之外,另一组系统服务源自 mediaserver 的启动。以下是 2.3/Gingerbread init.rc 中的相关片段(4.2/Jelly Bean 的版本几乎相同):
service media /system/bin/mediaserver
user media
group system audio camera graphics inet net_bt net_bt_admin net_raw
ioprio rt 4
mediaserver(源码在 2.3/Gingerbread 的 frameworks/base/media 和 4.2/Jelly Bean 的 frameworks/av/media)启动以下系统服务:音频流管理器(Audio Flinger)、媒体播放器服务(Media Player Service)、相机服务(Camera Service)和音频策略服务(Audio Policy Service)。同样,这些都不可配置,建议你不要修改 init.rc 的相关部分,除非你完全理解修改的影响。例如,如果你试图从 init.rc 中移除 mediaplayer 服务的启动,或使用 disabled 选项阻止其启动,你会在 logcat 输出中看到这样的消息:
...
I/ServiceManager( 56): Waiting for service media.audio_policy...
I/ServiceManager( 56): Waiting for service media.audio_policy...
W/AudioSystem( 56): AudioPolicyService not published, waiting...
I/ServiceManager( 56): Waiting for service media.audio_policy...
...
系统将挂起,并继续打印这些消息,直到 mediaserver 启动。
请注意,mediaserver 是使用 ioprio 选项的少数 init 服务之一。据推测——不幸的是没有官方文档确认——这用于确保媒体播放具有适当的优先级,以避免播放不流畅。
最后还有一个比较特殊的参与者:提供 Phone 系统服务的电话应用(Phone app)。一般来说,应用是放置系统服务的错误地方,因为应用是生命周期管理的,因此可以随意停止和重启。然而系统服务应该从启动到重启一直存在,因此不能在不影响系统其余部分的情况下中途停止。然而 Phone 应用不同,因为它的清单文件在 application XML 元素的 android:persistent 属性设置为 true。这向系统表明这个应用不应该被生命周期管理,从而使其能够承载一个系统服务。
这也导致这个应用作为活动管理器初始化的一部分被自动启动。
同样,关于 Phone 应用的启动,没有什么通常是可以配置的。不过,你相对容易地从内置于 AOSP 的应用列表中移除 Phone 应用。然而,结果是,依赖该系统服务的系统任何部分都将无法正常工作。再说一次,你不妨保留它。如果你想从主屏幕上移除拨号器图标,那你实际想要移除的是通讯录应用(Contacts app)。尽管这可能听起来违反直觉,但 Android 用户习惯的那个典型电话拨号器并不属于 Phone 应用——它是通讯录应用的一部分。
另一个包含系统服务的应用例子是 packages/apps/Nfc/ 中的 NFC 应用。
Phone 应用提供系统服务的方式非常有趣,因为它为我们打开了一扇门——我们可以效仿它的例子,将系统服务作为应用添加到我们自己的 device/acme/coyotepad/ 目录中,而无需修改 frameworks/base/services/ 中默认系统服务的源码。