说明
Android服务框架包括Java服务框架(Java层)和本地服务框架(C++层),两层通过JNI交互。
代码分析版本:Android 10
框架概览
静态分层结构
说明:Android服务框架可分为四层
- 服务层:包含特定功能函数的服务层。IFooService规定服务提供的函数,继承IInterface;FooManager引用IFooService;FooService继承Binder和IFooService。
- RPC层:客户端生成RPC代码和数据,服务端根据RPC代码查找对应函数并传递RPC数据。IFooService.Stub.Proxy持有BinderProxy引用,BinderProxy由用户检索服务时获得。IFooService.Stub为抽象类,由FooService或其成员实现。
- IPC层:将RPC代码和数据封装为Binder IPC数据,并传递给Binder Driver。
- Binder Driver层:根据Binder IPC数据查找指定服务并返回。
RPC层说明
- 客户端:调用Proxy具体方法,通过
BinderProxy.transact(code, data, reply, flag)
将方法名和入参等信息传给IPC层 - 服务端:调用
Stub.onTransact(code, data, reply, flag)
方法,根据code定位具体方法,根据data获取入参。
1 | // Proxy |
服务框架各类相互作用
- 注册服务。FooService发起服务注册请求,Java系统服务一般在SystemServer.run方法里实例化并注册。在Binder驱动里将服务注册为Binder节点,ContextManager持有该节点句柄。
- 检索服务。用户使用Context.getSystemService获取FooService,实际上是通过IPC从ContextManager 获取FooService,返回的是FooService的句柄,但客户端不能直接使用FooService,最终返回的是通过FooService生成的代理类(BinderProxy)的包装类FooManager。注意这个过程中会生成客户端的BinderProxy实例以及本地BpBinder实例,FooManager间接持有BinderProxy引用,BinderProxy间接持有本地BpBinder指针,这些对象在客户端使用服务时会涉及到。
- 使用服务。FooManager调用foo()函数,实际上调用代理类BinderProxy.transact()函数,后者通过JNI与本地BpBinder交互,并将数据传给Binder驱动进行IPC通信,通过IPCThreadState会调用FooService对应的本地BBinder实例,实际为其实现类JavaBBinder,后者会调用Java层的FooService(继承IFooService.Stub,后者继承Binder)的execTransact()方法,最终根据RPC代码查找到指定函数并执行。
注意:以上举例适用于Java服务,本地服务类似,需要将最上层的Java代码改为C++代码,细节待确定 TODO
主要类和文件
1 | java |
示例分析-AlarmManagerService
以应用层使用Java系统服务AlarmManagerService为例,基于代码分析服务的注册、检索和使用三个流程。
1 | // 1. SystemSever启动时,注册服务。 |
注册服务
Java系统服务在SystemServer进程启动时开始实例化并注册。首先调用SystemServer.main()方法,该方法内部会实例化SystemServer并调用其run()方法,run()方法中接着调用startOtherServices()方法,该方法中会执行AlarmManagerService的服务实例化和注册操作。
SystemServer.run()方法最后会调用Looper.loop()方法阻止线程退出,SystemServer实例会常住内存且持有SystemServiceManager实例引用,SystemServiceManager又持有系统服务集合,因此各个系统服务实例会常住系统内存,以供客户端调用。
1 | // 前置流程:SystemServer.main() -> SystemServer.run() -> startOtherServices() |
(1) mRemote初始化为BinderProxy流程
mRemote被声明为IBinder,在ServiceManagerProxy构造方法内进行初始化,而ServiceManagerProxy是通过ServiceManager.getIServiceManager()内调用静态方法ServiceManagerNative.asInterface(IBinder b)进行构造的。
ServiceManagerNative.asInterface(IBinder b)方法接收IBinder类型的参数,并最终赋值给ServiceManagerProxy里的mRemote变量。IBinder类型的参数由BinderInternal.getContextObject()通过JNI方式从本地获取。
1 | private static IServiceManager getIServiceManager() { |
(2) 如何从BBinder进入service_manager.c的binder_loop()方法中? TODO
检索服务
调用Context.getSystemService()方法,具体是调用ContextImpl.getSystemService()方法。
1 | // ContextImpl.java 通过name获取ServiceFetcher |
使用服务
调用AlarmManager.setTime()
1 | public void setTime(long millis) { |
(1) JavaBBinder本地代码调用Java代码 Binder.execTransact()
1 | // android_util_Binder.cpp |
参考
- 金泰廷等著《Android框架解密》,人民邮电出版社,2012。该书分析的代码较老,但框架机制基本不变,非常好的书籍。
- 源码查看网站:http://aospxref.com/。基于OpenGrok的源码查看服务网站,速度很快,主要用来查看C/C++代码,Java代码可下载到本地查看。