1. 课程导入
在Android系统中,应用进程与系统服务之间并不是直接调用,而是通过Binder驱动完成跨进程通信。每一个系统服务在启动后,都需要把自己的Binder句柄注册到ServiceManager中,客户端才能通过名称查询到它并建立连接。可以说,ServiceManager是Android服务体系的“电话总机”,而服务启动过程则是把各个系统能力接入这台总机的关键动作。本课程围绕“服务如何启动、如何注册、如何被查询、如何被使用”这条主线展开,帮助学习者建立从内核Binder到Framework层ServiceManager的完整工程认知。
一、核心概念:先建立四个关键角色
理解Android服务启动,首先要区分四个角色。第一是Binder驱动,它位于内核空间,负责进程间数据传递和句柄管理;第二是ServiceManager,它是系统启动最早的服务之一,负责维护“服务名称 → Binder引用”的映射表;第三是系统服务进程,例如system_server,它承载了大量Framework层服务;第四是客户端进程,它通过ServiceManager查询目标服务,拿到代理对象后发起调用。
这四个角色之间的关系可以用下面的结构图表示。图中同时标出了服务注册与服务查询两条方向相反的路径,便于理解ServiceManager作为中间枢纽的位置。
二、整体知识框架:从启动到调用的五层结构
本课程的知识框架可以划分为五层。第一层是Binder基础层,包括Binder驱动、Binder协议、Parcel序列化;第二层是ServiceManager层,包括服务注册、查询、权限校验和死亡通知;第三层是服务启动层,包括init进程解析rc文件、启动system_server、ServiceManager启动顺序;第四层是Framework服务层,包括SystemServiceManager、ServiceThread、BinderService等机制;第五层是工程实践层,包括自定义系统服务、SELinux策略配置、服务调试与排障。
| 层次 | 核心对象 | 关键动作 | 常见问题 |
|---|---|---|---|
| Binder基础层 | Binder驱动、Parcel | 打开设备、内存映射、数据收发 | 句柄泄漏、传输大小超限 |
| ServiceManager层 | ServiceManager、ServiceMap | addService、getService、listServices | 服务未注册、名称冲突 |
| 服务启动层 | init、rc脚本、system_server | 解析配置、fork进程、启动服务 | 启动顺序错误、权限不足 |
| Framework服务层 | SystemServiceManager、BinderService | onStart、publishBinderService | 服务启动超时、线程阻塞 |
| 工程实践层 | 自定义服务、SELinux策略 | 注册服务、配置te文件、调试 | avc denied、客户端拿不到服务 |
三、实战路线图:按工程顺序推进
学习本课程建议按照“先看启动顺序,再看注册机制,最后做自定义服务”的路线推进。具体可以分为六个阶段:
- 阶段一:观察启动日志。通过logcat和dmesg观察ServiceManager、system_server的启动顺序,确认服务注册的时间点。
- 阶段二:理解Binder注册。阅读addService和getService的调用链,理解Binder驱动如何维护句柄。
- 阶段三:分析system_server。查看SystemServer.java中startBootstrapServices、startCoreServices、startOtherServices的启动分组。
- 阶段四:编写自定义服务。实现一个继承Binder的本地服务,并通过ServiceManager注册。
- 阶段五:配置SELinux。为自定义服务添加type、allow规则和service_contexts配置。
- 阶段六:调试与验证。使用service list、dumpsys、logcat验证服务是否注册成功并可被调用。
# 查看当前已注册的系统服务
adb shell service list | head -n 20
# 查看某个服务的详细信息
adb shell dumpsys activity services
# 观察ServiceManager相关日志
adb logcat -s ServiceManager:V SystemServer:I
# 查看SELinux拒绝日志
adb shell dmesg | grep avc
四、典型场景与常见误区
在实际工程中,最常见的场景是“自定义系统服务启动后,客户端调用时报ServiceNotFound”。这类问题通常不是服务代码本身错误,而是注册时机、SELinux策略或服务名称不一致导致的。另一个高频场景是服务启动阻塞,例如在onStart中执行耗时操作,导致system_server启动超时,进而引发系统重启。
常见误区二:只关注Java层addService,忽略SELinux和init.rc配置。很多“服务注册失败”最终都定位到权限或启动顺序问题。
常见误区三:在服务启动阶段执行阻塞操作。系统服务启动有严格的时间窗口,阻塞会导致Watchdog触发。
本课程后续将围绕这条主线逐步展开:从Binder驱动的基本原理,到ServiceManager的注册与查询实现,再到system_server的启动流程,最终完成一个可运行的自定义系统服务。掌握这些内容后,你不仅能够读懂Android系统服务的启动日志,还能独立完成系统服务的定制、注册、权限配置与调试。