简介
ServiceManager进程是由init进程创建的。源码文件是service_native.c。它是Native层的、系统全局“服务端”的管理者。
每个应用进程和SystemServer进程都有1个ServiceManager对象。它以单例模式封装了ServiceManagerNative对象,提供对系统服务的“服务端”的缓存,并封装了向ServiceManager进程申请“服务端”的过程。
启动后做了些什么?
- 创建一个binder_state结构体;
- 系统调用open,以可读可写(O_RDWR)模式打开文件”/dev/binder”,返回“文件描述符”到binder_state -> fd;
- 创建一个binder_proc结构体保存Binder机制的全局信息;
- 系统调用ioctl(BINDER_VERSION),设置Binder Version;
- binder_state -> mapsize = 128*1024;
- 系统调用mmap,把binder_state -> fd映射到内存,返回“映射区地址“到binder_state -> mapped;
- 系统调用ioctl(BINDER_SET_CONTEXT_MGR),把Zygote进程设置为守护进程;
- 系统调用ioctl(BINDER_WRITE_READ),写入BC_ENTER_LOOP,告诉Binder驱动开始循环;
- 开始循环,在一次循环中有两步操作:第一步从Binder驱动读出一个binder_write_read;第二步解析这个binder_write_read,执行相应操作。
服务端注册到ServiceManager
以MediaService为例
1.获取ServiceManager对象在MediaService进程的客户端
在IServiceManager.cpp -> defaulteServiceManager():
- gDefaulteServiceManager是定义在Static.cpp中的单例;如果gDefaulteServiceManager不为null,直接返回;否则调用interface_cast
(ProcessState::self() -> getContextObject(NULL))创建。 - ProcessState::self() -> getContextObject(NULL)会返回一个句柄为0的BpBinder,即ServiceManager在通信层的客户端。
- 调用BpBinder.queryLocalInterface()获取ServiceManager业务层客户端在MediaService进程的实例,不为null则返回实例的指针;否则以BpBinder为参数创建一个BpServiceManager实例,并返回它的指针。
至此,MediaService进程有了一个指向BpServiceManager实例的指针。客户端向ServiceManager发送信息,相当于调用BpServiceManager的方法 ,转调BpBinder -> transtact(),转调IPCThreadState::self() -> transact()。
2.MediaService进程向Binder驱动写入数据
调用BpServiceManager -> addService(),转调BpBinder -> transtact(ADD_SERIVCE_TRANSACTION),转调IPCThreadState::self() -> transact():
- 向mOut写入指令吗BC_TRANSACTION;
- 创建一个binder_transaction_data,其中target.handle = 0,代表ServiceManager进程的句柄;code = ADD_SERIVCE_TRANSACTION,请求码;data_xxx 写入了三样: IServiceManager -> getInterfaceDescriptor()、name即“android.os.service_manager”、指向位于MediaService进程中的MediaService服务端的指针;
- 把binder_transaction_data写入mOut;
- 创建一个binder_write_read,其中“写”的部分为mOut,“读”的部分为mIn;
- 系统调用ioctl(BINDER_WRITE_READ),写入binder_write_read;
至此,MediaService进程向Binder驱动写入了一个binder_write_read。
3.ServiceManager进程从Binder驱动读出数据
数据是一个binder_write_read,其中指令码为BR_TRANSACTION,请求码为SVC_MGR_ADD_SERVICE。
- 转调service_manager.c -> do_add_service();
- 检测要注册的服务是否可以被添加到ServiceManager;只有当操作者是root或system进程,或者被添加的服务在allowed中定义过,才能被添加;
- 搜索svclist,看服务是否已经存在;如果不存在,创建svcinfo,并添加到svclist。
至此,service_manager.c -> svclist多了一个svcinfo,其中,handle为???,name为“android.os.service_manager”。
应用进程获取系统服务的服务端
在[Java]ServiceManager.getService()中:
- 查询缓存sCache中是否有服务名对应的”客户端”,如果有直接返回;
- 否则,获取ServiceManagerNative.ServiceManagerProxy的单例,调用它的getService();
- 在ServiceManagerProxy.getService()中,调用BpBinder.transact(),转入Native层;
- 向ServiceManager的缓冲区中写数据,其中请求码为GET_SERVICE_TRANSACTION,InterfaceToken为“android.os.IServiceManager“,参数为要请求的服务名;
- ServiceManager进程从Binder驱动读出一个binder_write_read,转调service_manager.c -> do_find_service();
- 搜索svclist,按name找到对应的scvinfo,并用scvinfo -> handle转换出一个指向BpBinder的指针,写入reply(Parcel)。
- 回到应用进程Java层,调用Parcel.nativeReadStrongBinder()从reply中读出IBinder对象,即为所需客户端;
- 把服务名、客户端存入缓存。